home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume26 / veos-2.0 / part14 < prev    next >
Encoding:
Text File  |  1993-04-25  |  88.4 KB  |  3,245 lines

  1. Newsgroups: comp.sources.unix
  2. From: voodoo@hitl.washington.edu (Geoffery Coco)
  3. Subject: v26i197: veos-2.0 - The Virtual Environment Operating Shell, V2.0, Part14/16
  4. Sender: unix-sources-moderator@vix.com
  5. Approved: paul@vix.com
  6.  
  7. Submitted-By: voodoo@hitl.washington.edu (Geoffery Coco)
  8. Posting-Number: Volume 26, Issue 197
  9. Archive-Name: veos-2.0/part14
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 14 (of 16)."
  18. # Contents:  docs/VEOS_The_Complete_Documentation
  19. #   src/kernel_current/shell/xv_glutils.c
  20. # Wrapped by vixie@efficacy.home.vix.com on Sun Apr 25 23:10:46 1993
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'docs/VEOS_The_Complete_Documentation' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'docs/VEOS_The_Complete_Documentation'\"
  24. else
  25. echo shar: Extracting \"'docs/VEOS_The_Complete_Documentation'\" \(41783 characters\)
  26. sed "s/^X//" >'docs/VEOS_The_Complete_Documentation' <<'END_OF_FILE'
  27. X
  28. X
  29. X
  30. X
  31. X
  32. X
  33. X
  34. X*******************************************************************************
  35. X
  36. X                    
  37. X                    
  38. X                The VEOS project
  39. X             Human Interface Technology Lab
  40. X                University of Washington
  41. X                  Seattle, WA
  42. X                    
  43. X                    
  44. X                    
  45. X                    VEOS 2.0
  46. X                    
  47. X                  Tool Builders Manual
  48. X                    
  49. X                    
  50. X                    
  51. X                    
  52. X                Geoffrey P. Coco
  53. X                  May 4, 1992
  54. X                    
  55. X                    
  56. X
  57. X
  58. X
  59. X*******************************************************************************
  60. X
  61. X
  62. X
  63. X
  64. X
  65. X
  66. X
  67. X
  68. X*******************************************************************************
  69. X
  70. X
  71. X
  72. X                    
  73. X                    
  74. X                 The VEOS Project Team:
  75. X                    
  76. X                    
  77. X                William Bricken
  78. X                   Geoff Coco
  79. X                    Dav Lion
  80. X                 Andy MacDonald
  81. X
  82. X                    
  83. X                    
  84. X                    
  85. X                    
  86. X                    
  87. X                    
  88. X*******************************************************************************
  89. X
  90. X
  91. X
  92. X
  93. X
  94. X
  95. X*******************************************************************************
  96. X
  97. X                   
  98. X                   CONTENTS:
  99. X                   
  100. X
  101. X* VEOS License Agreement
  102. X
  103. X
  104. X* What is VEOS
  105. X
  106. X
  107. X* Fundamentals of VEOS
  108. X    - Entities
  109. X    - The Grouple
  110. X    - Grouplespaces
  111. X    - Pattern Matching
  112. X
  113. X
  114. X* Components of the VEOS Kernel
  115. X    - Nancy
  116. X    - Talk
  117. X    - Shell
  118. X
  119. X
  120. X* Using VEOS from Lisp
  121. X    - Design Methodology Restated
  122. X    - VEOS Lisp Interface
  123. X    - Nancy Pattern Matching Language
  124. X    - How to Use the Kernel from Lisp
  125. X
  126. X
  127. X* Writing Software Tools in C
  128. X    - Philosophy (please read this section)
  129. X    - Building a Custom Entity with Lisp Interface
  130. X        
  131. X
  132. X*******************************************************************************
  133. X
  134. X
  135. X
  136. X
  137. X
  138. X*******************************************************************************
  139. X* 
  140. X* 
  141. X*          VEOS 2.0 Copyright (C) 1992 Geoffrey P. Coco,
  142. X*              Human Interface Technology Laboratory
  143. X* 
  144. X* 
  145. X* Permission to use, copy, or modify these programs and their documentation
  146. X* without fee for educational and research purposes only is hereby granted,
  147. X* provided that this copyright notice appears on all copies and supporting
  148. X* documentation.  For any other uses of this software, in original or modified
  149. X* form, including but not limited to distribution in whole or in part, specific
  150. X* prior permission must be obtained from HITL.  These programs shall not be
  151. X* used, rewritten, or adapted as the basis of a commercial software or hardware
  152. X* product without first obtaining appropriate licenses from HITL.  HITL makes no
  153. X* representations about the suitability of this software for any purpose.  It is
  154. X* provided "as is" without express or implied warranty.
  155. X* 
  156. X* HITL AND GEOFFREY COCO DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  157. X* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
  158. X* SHALL HITL NOR GEOFFREY COCO BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  159. X* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  160. X* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  161. X* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  162. X* OF THIS SOFTWARE.
  163. X* 
  164. X* 
  165. X* Questions about this software should be addressed to:                 
  166. X*                                             
  167. X*     Software Support                                
  168. X*      Human Interface Technology Laboratory                        
  169. X*       FJ-15, University of Washington                            
  170. X*       Seattle, Washington     98195    USA                        
  171. X*                                             
  172. X* or via email:                                    
  173. X*                                             
  174. X*       veos-support@hitl.washington.edu                        
  175. X*
  176. X*******************************************************************************
  177. X
  178. X*******************************************************************************
  179. X
  180. X                 What is VEOS?
  181. X
  182. X*******************************************************************************
  183. X
  184. X
  185. XVEOS is an extendable environment for prototyping distributed applications for
  186. Xunix.  The VEOS application programmer's interface is provided by XLISP 2.1 (by
  187. XDavid Betz).  XLISP provides familiar program control; VEOS provides
  188. Xinterprocess message passing and content addressable database access.
  189. X
  190. XVEOS (The Virtual Environment Operating Shell) was developed for distributed
  191. XVirtual Reality applications at The Human Interface Technology Lab in Seattle
  192. Xand has been in use for two years.  However, VEOS is by no means limited to
  193. Xthese types of applications.
  194. X
  195. XVEOS is ideal for applications where hardware resources are not physically
  196. Xproximal or where machine-dependent resources (e.g. software packages, interface
  197. Xdevices, etc..) are isolated because of their platform.
  198. X
  199. XVEOS is also ideal for prototyping programs which employ coarse grain
  200. Xparallellism.  That is, VEOS uses heavyweight sequential processes,
  201. Xcorresponding roughly to unix processes.  In this way, VEOS can be used to
  202. Xutilize a network of workstations as a virtual multiprocessor.
  203. X
  204. XC programmers can build custom VEOS tools which are accessable from XLISP and
  205. Xthus are immediately compatible with other VEOS tools.  Lisp programmers can
  206. Xquickly design and run distributed programs utilizing diverse hardware and
  207. Xsoftware resources.
  208. X
  209. XVEOS is not an operating system.  VEOS is a user-level framework for prototyping
  210. Xdistributed applications.  Its primary focus is flexibility and ease of use.
  211. XThis design comes somewhat at the expense of real-time performance.  This is not
  212. Xto say, however, that VEOS cannot achieve good performance with proper
  213. Xapplication structuring and tuning.
  214. X
  215. XRelying on only the most common unix interface, VEOS is platform independent.
  216. XVEOS 2.0 has been extensively tested on platforms such as DEC 5000, Sun 4, and
  217. XSilicon Graphics VGX and Indigo.
  218. X
  219. XVEOS, the Virtual Environment Operating Shell, is a software environment for
  220. Xprototyping distributed virtual world applications.
  221. X
  222. X*******************************************************************************
  223. X
  224. X*******************************************************************************
  225. X
  226. X                  Fundamentals of VEOS
  227. X
  228. X*******************************************************************************
  229. X
  230. X
  231. XWith VEOS, a programmer can specify how to accomplish the many computational
  232. Xtasks of a proposed virtual environment.  VEOS allows a programmer to clump
  233. Xthese tasks into computational nodes of a distributed system.  These clumps of  
  234. Xcomputational tasks are known as 'entities'.
  235. X
  236. XPresently in VEOS, each entity is implemented as a distinct Unix process with
  237. Xthe following native capabilities: interpretation of a coded task description
  238. X(presently written in lisp), inter-entity communication, generalized data
  239. Xmanagement (akin to tuple architecture), and generic pattern matching over local
  240. Xdata space.
  241. X
  242. XWith VEOS, a designer can implement a virtual environment using a set of
  243. Xentities, each residing on the same or different Unix based machines (presumimg
  244. Xnetwork accessibility).  Furthermore, because VEOS relies only on the most
  245. Xcommon Unix interface, one virtual environment application may utilize multiple
  246. Xhardware platforms.
  247. X
  248. XThe best method for utilizing VEOS entities as nodes in a distributed
  249. Xapplication greatly depends on the parameters of the applcation (e.g. the
  250. Xcomputational resources available, the topology of the network, the location and
  251. Xcompatibility of interface devices, etc..).  Consequently, the VEOS design,
  252. Xwhereever possible, foregoes making policy decisions so that the programmer
  253. Xenjoys maximum flexibility in designing a distributed application.
  254. X
  255. XVEOS programmers have had mixed results with various distributed models (e.g.
  256. XThe Fern System).  It should prove useful to study these prototypical models for
  257. Xsubtleties before attempting a full-scale distributed application with VEOS.
  258. X
  259. X
  260. X
  261. X                    Entities
  262. X                      ...
  263. X
  264. X
  265. XSince VEOS is intended as a software platform for distributed virtual
  266. Xenvironment applications, a primary design focus was the mechanism for
  267. Xspecifying the tasks and assigning computational resources in a distributed
  268. Xdesign.  The resulting model is the following.
  269. X
  270. XA VEOS application is broken down into distinct processes which are as
  271. Xself-reliant as possible (the more self-reliant, the more efficient the whole
  272. Xsystem will be).  Each process can be coded separately with provisions for
  273. Xcommunicating with the other processes in the system.  Each process is
  274. Ximplemented by a single VEOS entity on any network accessible Unix workstation.
  275. X
  276. XA VEOS entity, then, is a stand-alone executable program that is equipped with
  277. Xthe same VEOS native capabilities: data management, process management, and
  278. Xinter-entity communication.
  279. X
  280. X
  281. X                  The Grouple
  282. X                              ...
  283. X
  284. XOne of VEOS's aims is to support a consistent and general format for program
  285. Xspecification, inter-entity communication and database management.
  286. X
  287. X
  288. XIndependently, these needs can be solved by some existing methods.  For example,
  289. XLisp provides generalized data abstraction (i.e. lists), and useful program
  290. Xcontrol.  Mathematica provides a generalized specification format and consistent
  291. Xtreatment of data and function.  Linda provides generalized data management.
  292. X
  293. X
  294. XBut these tools do not share a common form.  In addition, large components of
  295. Xthese systems are extraneous for most situations.  Thus, intergrating such
  296. Xpackages would prove costly and wasteful.  Moreover, tying together such varied
  297. Xsystems emphasizes the differences between their respective forms and
  298. Xexpressions rather than their commonalities.
  299. X
  300. XConsequently, we chose an enhancement to the tuple as the VEOS general format.
  301. XThis format is called the 'grouple'.  Grouples can be seen as a nestable tuples.
  302. XGrouples are extrordinarily general for flexibility, yet the data they contain
  303. Xcan be accessed specifically for debugging and performance efficiency.  The
  304. Xsubfields of a grouple are called 'elements'.  As grouples can be nested, an
  305. Xelement can be a grouple.
  306. X
  307. XNancy, the VEOS data manager uses the grouple for it's standard data format.
  308. XTalk, the VEOS communications module, transports linearized grouple stuctures.
  309. X
  310. XVEOS now has a lisp interface.  The Lisp language was chosen because there is a
  311. Xclear mapping from lisp lists to VEOS grouples.  Furthermore, because lisp
  312. Xboasts program-data equivalence, programmers can store and pass fragments of
  313. Xentity specification using the VEOS kernel mechanisms.
  314. X
  315. X
  316. X                 Grouplespaces
  317. X                      ...
  318. X
  319. XTechnically, a grouplespace is an ordinary grouple.  There are two grouplespaces
  320. Xassociated with an entity which partition the entity's data according to the
  321. Xfollowing semantics.
  322. X
  323. XThe grouplespaces are: the workspace, the programmer's runtime database.  And
  324. Xthe inspace, where incoming inter-entity messages are placed.  In VEOS 2.0, the
  325. Xinspace has been bypassed as an efficiency concern.
  326. X
  327. X
  328. X                Pattern Matching
  329. X                      ...
  330. X
  331. XThe regime of pure algebraic reduction is well known to provide the ability to
  332. Xperform many kinds of computation (see prolog).  This scheme, also known as the
  333. XMatch/Substitute/Execute paradigm (ex. in expert systems) can be implemented
  334. Xusing a pattern matching mechanism.
  335. X
  336. XNancy supports pattern matching over its grouplespaces.  A pattern is a specific
  337. Xform that data can take.  Patterns can contain specific data to match or
  338. Xwildcard symbols which can be used to bind variables to values.  For specifics
  339. Xof the Nancy Pattern Matching Language, see the section Using VEOS from Lisp.
  340. X
  341. X
  342. X
  343. X*******************************************************************************
  344. X
  345. X             Components of the VEOS Kernel
  346. X
  347. X*******************************************************************************
  348. X
  349. X
  350. X            Nancy: The VEOS grouple manager
  351. X                         ...
  352. X
  353. XNancy is a homebrew database manager designed specifically for the VEOS project.
  354. XMuch like Linda systems manage data as tuples, Nancy mananges data as grouples.
  355. X
  356. XNancy performs all grouple manipulation within VEOS.  This involves creation,
  357. Xdestruction, insertion, copying, etc..  Since Nancy grouplespaces are merely
  358. Xnamed grouples, these are also an entity's fundamental database operations.
  359. X
  360. XIn addition, Nancy provides a powerful semantic for data searching, inserting
  361. Xand replaceing within a grouplespace.  This is the pattern matcher.  It is a
  362. Xcomplete set of primitives to implement a match/substitute/execute engine as in
  363. Xan expert system.
  364. X
  365. XFrom lisp, programmers have access to three Nancy operations, vput, vcopy and
  366. Xvget.  These are sufficient for all grouplespace operations.  As lisp
  367. Xexpressions are passed to these nancy primitives, they are converted to grouple
  368. Xformat and then handled by nancy's standard C interface.
  369. X
  370. X
  371. X
  372. X              Talk: The VEOS communications module
  373. X                            ...
  374. X
  375. XTalk is the only supported mechanism for entity communication.  As VEOS entities
  376. Xprovide coarse grain parallelism though Unix processes, process (entity)
  377. Xsynchronization and shared memory is not practical.  Thus VEOS supports message
  378. Xpassing as the only means of entity communication.
  379. X
  380. XTalk provides VEOS with two simple message passing primitives, vthrow and
  381. Xvcatch.  From lisp, programmers can transmit a message *asynchronously* to
  382. Xanother entity.  The receiving entity is then at leisure to receive the message,
  383. Xalso *asynchronously*.
  384. X
  385. XAsynchronous message passing means this: When an entity tranmits a message, the
  386. Xoperation succeeds *reliably*, whether the receiver is waiting for a message or
  387. Xnot.  Likewise, an entity can always check for incoming messages without waiting
  388. Xindefinitely for a message to arrive.  This is also called non-blocking
  389. Xcommunication.
  390. X
  391. XTalk passes messages between entities with a flat linearized grouple format.
  392. XThe lisp/veos interface module performs this translation.
  393. X
  394. X
  395. X
  396. X             Shell: The VEOS kernel control module
  397. X                            ...
  398. X
  399. XThe shell is the administrative workings of the VEOS kernel.  It dispatches
  400. Xinitializations, interrupt handling, manages kernel memory, etc..
  401. X
  402. X
  403. X*******************************************************************************
  404. X
  405. X                  Using VEOS from LISP
  406. X
  407. X*******************************************************************************
  408. X
  409. X
  410. X    ----------------
  411. X  veos methodology
  412. X----------------
  413. X
  414. X
  415. Xthe veos kernel provides:
  416. X
  417. X    1. fast and powerful local database access.
  418. X         - built-in pattern matching.
  419. X         - internal grouple form converts to lisp lists.
  420. X
  421. X    2. clean and reliable message passing.
  422. X         - utilizes Berkeley sockets.
  423. X         - symbolic entity addressing.
  424. X
  425. X    3. well defined C interface.
  426. X         - can be retrofit to any high-level language (like lisp).
  427. X
  428. X
  429. X
  430. X    ---------------------
  431. X  getting your feet wet
  432. X---------------------
  433. X
  434. X
  435. X*  Get an account on a Unix machine that supports VEOS (Suns, DECs, SGs).
  436. X
  437. X*  Make sure /home/veos/bin/ is in your path.
  438. X
  439. X*  You are ready to run a basic VEOS entity.  The basic VEOS entity with is built
  440. X   with an xlisp interface.  What you get is complete xlisp plus the VEOS native
  441. X   primitives described in the next section.
  442. X   You can run entities at least two ways:
  443. X
  444. X   1. Type 'entity' at the Unix command line.  
  445. X
  446. X   2. Alternatively (and recommended), you can run entities from inside emacs.
  447. X
  448. X      Within emacs, do meta-x eval-expression:
  449. X         (setq inferior-lisp-program "/home/veos/bin/entity")
  450. X      or put this line in your .emacs file.
  451. X
  452. X      Then, do meta-x run-lisp.  Once in this emacs mode, you can do meta-x
  453. X      describe-mode to learn about fancy emacs features with respect to lisp
  454. X      interaction.
  455. X
  456. X*  To load a program into lisp, type (load "filename.lsp") to lisp.
  457. X
  458. X
  459. X
  460. X    ---------------------
  461. X  veos kernel interface
  462. X---------------------
  463. X
  464. X  Currently xlisp provides the abstract access to veos kernel capabilities.  The
  465. X  following describes the native priitives as of February 8, 1992.
  466. X
  467. X
  468. X  startup veos kernel from lisp
  469. X  '''''''''''''''''''''''''''''
  470. X           (vinit <port number> )
  471. X        ; initialize veos kernel,
  472. X        ; establish network port for incoming messages.
  473. X        ; if port number is not given, veos chooses an available port.
  474. X        ; vinit returns uid of this entity upon success
  475. X
  476. X
  477. X  takedown veos kernel from lisp
  478. X  ''''''''''''''''''''''''''''''
  479. X        (vclose)
  480. X        ; takedown veos kernel,
  481. X        ; cleanup network connections.
  482. X        ; xlisp (exit) function will also perform necessary veos takedown.
  483. X
  484. X
  485. X  kernel system tasking
  486. X  '''''''''''''''''''''
  487. X        (vtask)
  488. X        ; pass control to veos kernel to perform network activity.
  489. X        ; for best performance, call vtask every time through
  490. X        ; the entity's main loop, calling (vcatch) immediately
  491. X        ; afterward.
  492. X
  493. X
  494. X  local grouplespace access
  495. X  '''''''''''''''''''''''''
  496. X        (vput <data element> <nancy pattern> :freq <"all"> )
  497. X        ; add data to local grouplespace.
  498. X        ; data element can be a list.
  499. X        ; pattern for vput may contain ^.
  500. X        ; optional frequency key-argument ("all" is only value allowed)
  501. X        ; requests exaustive matching.
  502. X
  503. X        (vcopy <nancy pattern> :test-time <time-stamp> :freq <"all"> )
  504. X        ; non-destructive local grouplespace query.
  505. X        ; pattern for vcopy may not contain ^.
  506. X        ; optional timestamp key-argument must be created by (vmintime)
  507. X        ; given timestamp is modified in place.
  508. X
  509. X        (vget <nancy pattern> :freq <"all"> )
  510. X        ; destructive local grouplespace query.
  511. X        ; pattern for vget may not contain ^.
  512. X
  513. X        (vmintime)
  514. X        ; returns a guaranteed oldest time stamp.
  515. X
  516. X        ; see below for nancy pattern language specification.
  517. X
  518. X
  519. X  message passing
  520. X  '''''''''''''''
  521. X        (vthrow (destination1 destination2 ...) (lisp expression) )
  522. X        ; send to a list of desinations.
  523. X        ; list may contain zero or one destination, and
  524. X        ; the same destination may appear more than once.
  525. X        ; destination is lisp vector of hostname and port number,
  526. X        ; ex.  '#("vorpal" 7800)
  527. X        ; message is appended to each desination's incoming grouplespace.
  528. X
  529. X           (vcatch <nancy pattern> )
  530. X        ; perform standard nancy pattern match from incoming grouplespace.
  531. X        ; acts like vget in all other ways.
  532. X        ; since new messages are appended, oldest message is at top.
  533. X        ; to simply retrieve oldest message, use: (vcatch '(> @ @@)).
  534. X        
  535. X        ; NOTE: currently, VEOS 2.0 does not support 
  536. X        ; the pattern argument for efficiency reasons.
  537. X        ; (vcatch) simply returns the oldest available message.
  538. X
  539. X
  540. X    -------------------------
  541. X  caveats of xlisp for veos
  542. X-------------------------
  543. X
  544. XThere are many types of VEOS data elements.  The most common and useful element
  545. Xtypes to programmers are available from lisp.  The VEOS types that are supported
  546. Xby lisp are:
  547. X
  548. X     VEOS                               equivalent in Lisp
  549. X    ------                           --------------------
  550. X
  551. X    grouple                            list - NIL or () is the empty grouple
  552. X
  553. X    integer                               integer - use a regular number
  554. X
  555. X    float                              float - use a decimal point
  556. X
  557. X    string                             string - use "" to make a string
  558. X
  559. X
  560. XLikewise, lisp supports many data element types.  There is an equivalent data
  561. Xelement in VEOS for some of these.  The data elements that VEOS supports are
  562. Xthose listed above and the following:
  563. X
  564. X     Lisp                               equivalent in VEOS
  565. X    ------                             --------------------
  566. X
  567. X    symbol *                          prim type.
  568. X
  569. X    vector                             special grouple
  570. X
  571. X
  572. X* A symbol in lisp can be used for a variable, function, or be unbound.  When a
  573. X  lisp symbol is passed to VEOS (for grouplespace storage of message passing),
  574. X  VEOS retains the name of the symbol but not the bindings.  Lisp normally retains
  575. X  these symbol bindings.  
  576. X
  577. XAll other lisp data types are unsupported by VEOS.  This means that they cannot
  578. Xbe passed to Nancy for grouplespace storage.  And they cannot be used within
  579. Xinter-entity messages.
  580. X
  581. X
  582. X    -------------------------------
  583. X  nancy pattern matching language
  584. X-------------------------------
  585. X
  586. XNancy controls access to the grouplespaces through a pattern matching language.
  587. XThe goals of the language are to provide a succinct format to express the locale
  588. Xin the grouplespace you would like to work and what you would like to do there.
  589. X
  590. XThere are three fundamental grouplespace operations that Nancy provides:
  591. X
  592. X   - find some location (specified by pattern), insert data there.
  593. X   - find some data (specified by pattern), retrieve it.
  594. X   - find some data (specified by pattern), retrieve it and replace it with
  595. X     other data.
  596. X
  597. X
  598. X
  599. XThus, these are the rules of nancy pattern matching:
  600. X
  601. XTo find anything (called a site), specify a pattern.  Patterns consist of
  602. Xinformation about where the site is and/or specific data that the site contains.
  603. X
  604. X    The ^ (void) symbol specifies a location within a grouple for inserting.  It
  605. X    points to the void between data.  Technically, the ^ always matches.
  606. X
  607. X    The > (mark) symbol points to a piece of data within a grouple retrieval or
  608. X    replacement operation.  It designates the immediately following element of
  609. X    the pattern as the site of action.  The > does not itself match data.
  610. X
  611. X
  612. XFor a pattern to be meaningful, one of these symbols (^ or >) must appear
  613. Xsomewhere in the pattern.  In other words, the pattern must always specify a
  614. Xsite of action.
  615. X
  616. XTo match data within a pattern, you can either specify actual data to compare,
  617. Xor wildcard symbols which are content-blind.
  618. X
  619. X    The @ (this) symbol specifies a single element at a specific location within
  620. X    a grouple.  This will match any single element including a grouple.
  621. X
  622. X    The @n (these) symbol specifies exactly n sequential elements within a
  623. X    grouple.  This will match the next n elements.  @1 is equivalent to @.
  624. X
  625. X    The @@ (these all) symbol specifies zero or more elements within a grouple.
  626. X    This will match all the remaining elements in a grouple.  This special form
  627. X    is allowed only at the end of a pattern grouple.
  628. X
  629. X    The ** (any) symbol specifies zero or more elements *anywhere* within a
  630. X    grouple.  This will match all the remaining unmatched elements in a grouple.
  631. X    This special form is allowed only at the end of a pattern grouple.
  632. X
  633. X    The ~ (touch) symbol specifies that the immediately following element be
  634. X    'touched' during a (vput ...) operation.  That is, the data that matches
  635. X    the pattern symbol following the ~ is marked as having been recently
  636. X    modified.  There can be any number of ~ in a pattern.
  637. X
  638. X    Anything else is taken literally and compared with the actual data in the
  639. X    grouplespace.
  640. X
  641. X    Note that nancy patterns are recursive.  That is, a pattern may
  642. X    contain a grouple which may contain wildcards and data, some of which
  643. X    are more grouples, etc..
  644. X
  645. X
  646. XExamples.
  647. X
  648. XHere is an actual session with lisp.  My comments are added.
  649. X
  650. X;; we begin with an empty grouplespace, ie ().
  651. X;; to vput, we match the grouplespace and point to the void within it.
  652. X;; thus, the (^) pattern.
  653. X;; this is literally where the given data is put.
  654. X
  655. X> (vput "first" '(^))
  656. XT
  657. X
  658. X;; here, we reqeusted a simple insert operation.  so vput vput return T or NIL
  659. X;; depending on the success of the match.  during a replace vput operation, vput
  660. X;; returns what your action replaced in the grouplespace.  in a moment, we'll
  661. X;; see when this comes into play.
  662. X
  663. X
  664. X
  665. X;; to see the entire contents of the grouplespace, we need to do a
  666. X;; nondestructive query.  the most succinct way to do this is to match the
  667. X;; grouplespace and copy all of its elements:
  668. X
  669. X> (vcopy '(> @@))
  670. X("first")
  671. X
  672. X;; note that the @@ can match a single element if there is only one, or it can
  673. X;; match many elements if there are more than one.  in the latter case, the
  674. X;; results are conveniently returned in a list.  in the interest of consistency,
  675. X;; all nancy results are returned in lists.
  676. X
  677. X
  678. X
  679. X;; let's now insert a list after the first element of the grouplespace:
  680. X
  681. X> (vput '("third") '(@ ^))
  682. XNIL
  683. X
  684. X;; again, no data was removed in the process.
  685. X
  686. X
  687. X
  688. X;; the entire contents...
  689. X
  690. X> (vcopy '(> @@))
  691. X("first" ("third"))
  692. X
  693. X
  694. X
  695. X;; let's now insert an element between the first element and all the rest of the
  696. X;; elements in the grouplespace.
  697. X
  698. X> (vput "second" '(@ ^ @@))
  699. XNIL
  700. X
  701. X;; note that (@ ^ @) would have also worked anbd would have been more precise.
  702. X
  703. X
  704. X
  705. X;; inspect the entire contents
  706. X
  707. X> (vcopy '(> @@))
  708. X("first" "second" ("third"))
  709. X
  710. X
  711. X
  712. X;; here, we are inserting a vector into the grouplespace.
  713. X;; this demonstrates two other features.  the @2, in the given position in
  714. X;; the pattern matches the first two elements of the grouplespace.  the "third" in
  715. X;; the pattern matches the actual data in the grouplespace.  this, of course, is
  716. X;; unlike how an @ matches any element where no data is compared.
  717. X
  718. X> (vput '#(1.4 3.9 9.0) '(@2 ("third" ^)))
  719. XNIL
  720. X
  721. X
  722. X
  723. X;; the data now resides where the ^ was in the previous pattern.
  724. X
  725. X> (vcopy '(> @@))
  726. X("first" "second" ("third" #(1.4 3.9 9)))
  727. X
  728. X
  729. X
  730. X;; sometimes it is useful to replace existing data in the grouplespace.
  731. X;; this can be done by removing, then inserting correct data.
  732. X;; or it can be done with a replacing vput.
  733. X;; here, we replace the first element of the grouplespace with the given data.
  734. X;; we must also match the remaining elements in the grouplespace to achieve a
  735. X;; successful match.
  736. X
  737. X> (vput "uno" '(> @ @@))
  738. X("first")
  739. X
  740. X;; vput returns the removed data.
  741. X
  742. X
  743. X
  744. X;; and the first element has been replaced.
  745. X
  746. X> (vcopy '(> @@))
  747. X("uno" "second" ("third" #(1.4 3.9 9)))
  748. X
  749. X
  750. X
  751. X;; now, let's look at the more subtle features of pattern matching.  begin by
  752. X;; emptying the current contents of the grouplespace to begin a new session.
  753. X
  754. X> (vget '(> @@))
  755. X("uno" "second" ("third" #(1.4 3.9 9)))
  756. X
  757. X
  758. X;; confirm that the grouplespace is empty
  759. X
  760. X> (vcopy '(> @@))
  761. XNIL
  762. X
  763. X
  764. X;; here, we'll insert some new data
  765. X
  766. X> (vput '("animal" "giraffe") '(^))
  767. XT
  768. X> (vput '("plant" "fern") '(^ @))
  769. XT
  770. X> (vput '("animal" "lion") '(^ @2))
  771. XT
  772. X> (vcopy '(> @@))
  773. X(("animal" "lion") ("plant" "fern") ("animal" "giraffe"))
  774. X
  775. X
  776. X
  777. X;; now we can perform useful matches on the grouplespace.  suppose we want to
  778. X;; find the tag associated with the "fern" data.  we simply ask for the element
  779. X;; immediately preceding the "fern" element.  note the use of the ** wildcard.
  780. X;; the ** pattern element has two functions in this pattern.  first, like @@ it
  781. X;; matches all the reminaing elements in the grouple.  second, it explicitly
  782. X;; makes the containing grouple an order-independent pattern.  in other words,
  783. X;; when nancy sees a ** in a pattern grouple, it ignores the order of the source
  784. X;; (grouplespace) elements when matching; it matches purely by content.
  785. X
  786. X> (vcopy '((> @ "fern") **))
  787. X("plant")
  788. X
  789. X;; note that although the marked element is "plant", but the result is contained
  790. X;; within an extra grouple.  as explained above, all nancy results are contained
  791. X;; within a grouple.
  792. X
  793. X
  794. X
  795. X
  796. X;; if we want to find the data associated with the tag "animal", we can do a
  797. X;; similar match.
  798. X
  799. X> (vcopy '(("animal" > @) **))
  800. X("lion")
  801. X
  802. X
  803. X
  804. X
  805. X;; but this is only a partial answer.  because there is more than one instance
  806. X;; of the tag "animal" at that level of the grouplespace.  we may want all the
  807. X;; possible matches of this form.
  808. X
  809. X> (vcopy '(("animal" > @) **) :freq "all")
  810. X("lion" "giraffe")
  811. X
  812. X
  813. X;; we can also use this feature with vput to do an exaustive replace.  here,
  814. X;; xlisp allows the arguments to a function to appear on consecutive lines.
  815. X
  816. X> (vput "mammal"
  817. X        '((> "animal" @) **)
  818. X        :freq "all")
  819. X("animal" "animal")
  820. X
  821. X;; vput returns exactly what it replaced.  
  822. X;; check that the replace was successful.
  823. X
  824. X> (vcopy '(> @@))
  825. X(("mammal" "lion") ("plant" "fern") ("mammal" "giraffe"))
  826. X
  827. X
  828. Xnow let's look at the pattern matching features that correspond to the
  829. Xdynamic issues of maintaining the grouplespace.  specifically, matching that
  830. Xis sensitive to the relative ages of the data can be used for so-called
  831. X'delta matching'.  we can use the previous contents to illustrate.
  832. X
  833. Xfirst, we'll make a nancy time stamp. 
  834. X
  835. X> (setq ts (vmintime))
  836. X0
  837. X
  838. X
  839. X;; we'll use this time stamp with vcopy.  if you pass a time stamp to vcopy, it
  840. X;; perform the given match but only returns matched data that is *younger* than
  841. X;; the time stamp.  vmintime returns a guaranteed oldest time-stamp.  this means
  842. X;; that using it will guarantee seeing everything in the grouplespace.
  843. X
  844. X> (vcopy '(> @@) :test-time ts)
  845. X(("mammal" "lion") ("plant" "fern") ("mammal" "giraffe"))
  846. X
  847. X;; vcopy compared all the matched data against the time stamp, all of it had
  848. X;; been modified (with vput) after the time given by the time stamp.
  849. X
  850. X
  851. X
  852. X;; vcopy *modifies* your time stamp in place to reflect that you've matched with
  853. X;; that pattern.  and as you can see, the time stamp has now been modified.
  854. X
  855. X> ts
  856. X1.4013e-44
  857. X
  858. X
  859. X
  860. X;; if we make the same match again with the same time stamp, we see no data.
  861. X;; this corresponds to there being no change (or delta) in the data since we
  862. X;; last matched.
  863. X
  864. X> (vcopy '(> @@) :test-time ts)
  865. XNIL
  866. X
  867. X
  868. X
  869. X;; let's insert some new data to see how the delta will be shown.
  870. X
  871. X> (vput '("mammal" "fox") '(> (@ "lion") **))
  872. X(("mammal" "lion"))
  873. X
  874. X
  875. X
  876. X;; when we match the entire grouplespace with our time stamp, we only get the
  877. X;; new data, since it was added since our last match.
  878. X
  879. X>  (vcopy '(> @@) :test-time ts)
  880. X(("mammal" "fox"))
  881. X
  882. X
  883. X
  884. X;; again the time stamp has been modified in place to reflect a new matching.
  885. X;; here we inspect the time stamp only to show that is has been changed.  the
  886. X;; actual value in the time stamp is irrelevant - it used internally by nancy.
  887. X
  888. X> ts
  889. X1.82169e-44
  890. X
  891. X
  892. X
  893. Xnotice that above we replaced both the data and the tag ("mammal" "fox") in
  894. Xthe grouplespace.  suppose that we want to replace only the data in the
  895. Xgrouplespace.
  896. X
  897. X> (vput "carrot" '((@ > "fern") **))
  898. X("fern")
  899. X
  900. X> (vcopy '(> @@) :test-time ts)
  901. X(("carrot"))
  902. X
  903. X;; as expected, vcopy returns only the changed data.
  904. X
  905. X
  906. X
  907. X;; above, the changed data is ambiguous without its tag.  but the tab was not
  908. X;; modified and so is not returned.  we can use the 'touch' feature during a
  909. X;; vput to mark elements in the grouplespace as having also been modified.
  910. X
  911. X> (vput "palm" '((~ @ > "carrot") **))
  912. X("carrot")
  913. X
  914. X;; note the ~ pattern modifier.  if the pattern successfully matches, nancy
  915. X;; 'touches' the element following the ~ in the pattern as having been modified.
  916. X
  917. X
  918. X
  919. X> (vcopy '(> @@) :test-time ts)
  920. X(("plant" "palm"))
  921. X
  922. X;; and this is exactly what we wanted.
  923. X;; unlike the > or ^ symbols, you can any number of ~ in a vput pattern.
  924. X
  925. X
  926. X
  927. X;; it is important to remember that a single time stamp represents the most
  928. X;; recent match of a *particluar* pattern from a *particular* point of view.
  929. X;; for example, if you're writing program for a server entity to which many
  930. X;; entities make matching requests, the server should maintain a time stamp for
  931. X;; each entity and each pattern type.  see the fx.lsp file of the Fern System
  932. X;; for examples of this strategy.
  933. X
  934. X
  935. X    ---------------------
  936. X  how to use the kernel
  937. X---------------------
  938. X
  939. X    - since all behavior description is specified in lisp, (and thus all
  940. X      kernel primitive composition), lisp's native evaluation mechanism is
  941. X      best suited to direct flow control.
  942. X
  943. X    - it is an explicit goal of veos to provide program distribution
  944. X      services to generic programming frameworks.  that is, the language we
  945. X      supplant above veos must be independent of the kernel
  946. X      implementation.  were process control a kernel resposibility, the
  947. X      kernel would require language-specific maintenance and would directly
  948. X      oppose the stated fundamental premise.
  949. X
  950. X    - the mechanism in lisp for handling entity process management is available.
  951. X      it consists of a main processing loop as described below.  each pass
  952. X      through the loop can be thought of as a 'frame'.  that is, one complete
  953. X      cycle through all an entity's responsibilities constitutes a quanta
  954. X      of entity activity.
  955. X
  956. X
  957. X      1. invoke kernel maintenance.
  958. X
  959. X         this entails polling network, garbage collection, etc..
  960. X
  961. X
  962. X      2. gather waiting inter-entity messages.
  963. X
  964. X         this process can be augmented by filtering.  In VEOS 2.0,
  965. X         this filtering feature has been disabled for performance reasons.
  966. X
  967. X
  968. X      3. evaluate messages from (2).
  969. X
  970. X         implemented with lisp's eval.
  971. X
  972. X            eval directs program control to the 'program stubs' contained
  973. X         within the messages.  thus, messages are single lisp
  974. X         expressions.  for example, the message:
  975. X                (add-to-database (frog x1 y1) (bird x2 y2))
  976. X         is a program stub that when evaluated by lisp will invoke the
  977. X         function 'add-to-database' with the arguments (frog x1 y1)
  978. X         and (bird x2 y2).
  979. X
  980. X
  981. X      4. give processing burst to background tasks.
  982. X
  983. X     remember that each entity is a single unix process.  and in general, a
  984. X     process is the smallest grain of parallelism that unix supports.
  985. X     consequently, there is no explicit provision in veos for concurrency
  986. X     (e.g. lightweight threads) *within* an entity.
  987. X
  988. X     but sometimes it is conceptually easier to design a program with
  989. X     concurrency in mind.  this desire for parallelism can be fulfilled
  990. X     with virtual processes.
  991. X
  992. X     given this regime of processing 'frames', programmers may simulate
  993. X     concurrent processes with discrete background tasks.  these tasks can
  994. X     be implemented as functions (program stubs) which perform a frame of
  995. X     computation and quickly return.  
  996. X
  997. X         the process table is a lisp association list of program stubs.
  998. X     program stubs are small fragments of lisp code that can compose an
  999. X     entity's behavior program stubs should never block.
  1000. X
  1001. X    - an entity's main processing loop can be expressed in lisp by:
  1002. X
  1003. X          (defun go ()
  1004. X                (loop
  1005. X                  (do-frame)))
  1006. X
  1007. X              (defun do-frame ()
  1008. X        (progn
  1009. X
  1010. X                  ;; kernel maintenance
  1011. X          (vtask)
  1012. X
  1013. X                  ;; gather and evaluate waiting messages
  1014. X                  (do ((msg (vcatch)))
  1015. X                        ((null msg))
  1016. X
  1017. X                      (eval msg)
  1018. X                      (setq msg (vcatch))
  1019. X                      )
  1020. X
  1021. X                  ;; give processing burst to background processes
  1022. X                  (dolist (proc background-procs)
  1023. X                  (eval (cadr proc)))
  1024. X                  ))
  1025. X
  1026. X
  1027. X    - since VEOS is intended as a prototyping system, the design is based
  1028. X      less on performance considerations and more on reliable functionality.
  1029. X      you will notice that the above scheme ignores many real-time issues.
  1030. X
  1031. X      for example, messages may arrive while an the entity is servicing
  1032. X      background processes.  thus, messages must wait an average of half the
  1033. X      time of a processing frame before being evaluated.  thus, when an
  1034. X      entity is heavily loaded, there may be significant latency in message
  1035. X      passing.  this can be troublesome when attempting to sychronize
  1036. X      entities though message passing.
  1037. X
  1038. X      likewise, important work may be waiting in the backgound processes while
  1039. X      the entity is servicing messages.  this can be troublesome when
  1040. X      attempting to ensure reliable interface device update rates.
  1041. X
  1042. X      these problems can be lessened through judicious use of inter-entity
  1043. X      messages (i.e. as few and small as possible) and through efficient and
  1044. X      sparing use of background tasks.
  1045. X
  1046. X
  1047. X    - The Fern System is a good example of how to use VEOS from lisp.  It
  1048. X      is included with the VEOS distribution.
  1049. X
  1050. X*******************************************************************************
  1051. X                    
  1052. X              Writing Software Tools in C
  1053. X
  1054. X*******************************************************************************
  1055. X
  1056. X
  1057. X== Philosophy ==
  1058. X
  1059. XAny software tool can be integrated with VEOS.  However, certain features of
  1060. Xsoftware tools make them easier to integrate.  The process of VEOSifying a
  1061. Xsoftware tool is writing custom lisp primitives (usually in C) which decode lisp
  1062. Xarguments and pass control to the software tool.
  1063. X
  1064. XGiven that all control will be passed to a tool via lisp primitives, the
  1065. XVEOSified tool will perform best if it is:
  1066. X
  1067. Xnon-blocking:
  1068. X    That is, primitives should always return after a reasonable slice of time
  1069. X    (depends on application).
  1070. X
  1071. Xinterrupt-driven is ok:
  1072. X    As long as primitive entry points appear to accomplish their tasks quickly
  1073. X    (use static caches, etc..).  In fact, for polling type software tools (input
  1074. X    device drivers, etc..), interrupts are preferrable to timeout reads in some
  1075. X    situations.  Especially when data arrival is infrequent.
  1076. X
  1077. Xmodular:
  1078. X    The tool should perform distinct, well-defined tasks.  This assists the lisp
  1079. X    programmer with task specification.  And it makes writing custom primitives
  1080. X    easy.
  1081. X
  1082. Xrobust:
  1083. X    Eg, can handle lags in data flow, can handle out-of-band data, etc..
  1084. X    Remember, world designers will want to rely on these distributed services.
  1085. X
  1086. X
  1087. X
  1088. X
  1089. X== Building a Custom Entity with Lisp Interface ==
  1090. X
  1091. X
  1092. XThe xlisp that is bound with with VEOS is a software library that anybody can
  1093. Xuse.  You can compile the xlisp library once, then link in user-defined lisp
  1094. Xprimitives at runtime.  Or, you can recompile xlisp by declaring user-defined
  1095. Xprimitives in advance as the xlisp documentation describes.  This section only
  1096. Xdescribes the dynamic scheme for binding xlisp primitives.
  1097. X
  1098. XTo use this version of xlisp, you need to provide two functions that xlisp
  1099. Xexpects.
  1100. X
  1101. XThe first function ( xlinclude_hybrid_prims() ) supplies xlisp with the function
  1102. Xpointers of your user-defined primitives (also called hybrid primitives).  If
  1103. Xyou're not binding any user-defined primitives (ie. making basic xlisp w/o
  1104. XVEOS), this function should have an empty body.  See file
  1105. X/home/xlisp/xexec/c/main.c for an example of the bare-bones main.
  1106. X
  1107. XThe second function ( xlhybrid_shutdown() ) gives user defined modules a chance
  1108. Xto clean their respective environments become xlisp exits.  xlisp will call this
  1109. Xfunction just before a graceful exit.  Again, if no special actions are to be
  1110. Xtaken, give this function an empty body.
  1111. X
  1112. XLastly to use this version of xlisp, you need to provide a main() function.  In
  1113. Xyour main(), do any setup that is required, then call xlisp's main ( xmain() ).
  1114. Xxmain() will never return.  Notice that VEOS does not do any setup in main()
  1115. X(see example file below).  Instead, kernel setup is a lisp primitive.  This
  1116. Xpractice is encouraged since it allows users to decide when to use particular
  1117. Xmodules.
  1118. X
  1119. XWhat follows are the step-by-step instructions to build a VEOS entity with xlisp
  1120. Xand and other custom software tools:
  1121. X
  1122. X1. Create a main control file that minimally looks like this:
  1123. X
  1124. X
  1125. X/***************************************************************************************
  1126. X * Copyright (C) 1992  Human Interface Technology Lab, Seattle                *
  1127. X ****************************************************************************************/
  1128. X
  1129. X#include "world.h"
  1130. Xextern xmain();
  1131. X
  1132. X
  1133. X/***************************************************************************************
  1134. X * main
  1135. X * launchpad of any stand-alone program
  1136. X ****************************************************************************************/
  1137. Xmain(argc, argv)
  1138. X    int        argc;
  1139. X    char    *argv[];
  1140. X{
  1141. X    /** call the xlisp controller, never returns **/
  1142. X    xmain(argc, argv);
  1143. X    }
  1144. X
  1145. X
  1146. X/***************************************************************************************
  1147. X * xlinclude_hybrid_prims
  1148. X * lisp calls this function to load user-defined lisp primitives
  1149. X ****************************************************************************************/
  1150. Xxlinclude_hybrid_prims()
  1151. X{
  1152. X    /** load veos native lisp primitive entries.
  1153. X     ** this function lives in the xvnative_glue library
  1154. X     **/
  1155. X    Shell_LoadNativePrims();
  1156. X
  1157. X
  1158. X    /** here, make calls to other software tool setup functions **/
  1159. X    MyModule_LoadMyPrims();    
  1160. X    }
  1161. X
  1162. X
  1163. X
  1164. X/***************************************************************************************
  1165. X * xlshutdown_hybrid
  1166. X * lisp calls this function before graceful exit
  1167. X ****************************************************************************************/
  1168. Xxlshutdown_hybrid()
  1169. X{
  1170. X    /** let the kernel unwind
  1171. X     ** this function lives in the kernel library
  1172. X     **/
  1173. X    Kernel_Shutdown();
  1174. X
  1175. X    /** here, make calls to other software tools shutdown code **/
  1176. X    }
  1177. X
  1178. X
  1179. X2. Create a file that contains your primitives.  Write C functions which handle
  1180. X   lisp arguments.  These functions are the glue between your software and
  1181. X   lisp (ie. your primitives).  See the kernel interface files, xv_native.c and
  1182. X   xv_glutils.c, for model code.  You may use any of the utilities found in
  1183. X   these files.  The functions themselves are compiled into the xvnative_glue
  1184. X   library.
  1185. X
  1186. X   In this file, provide xlisp with the function pointers to your primitives.  In
  1187. X   step 1, the function xlinclude_hybrid() loads all the user-defined prims.  In
  1188. X   addition to loading the native kernel primitives, it should call a function like
  1189. X   this to load your primitives into lisp:
  1190. X
  1191. X
  1192. X#include "xlisp.h"
  1193. X
  1194. X/***************************************************************************************
  1195. X * MyModule_LoadMyPrims
  1196. X * load user-defined lisp primitives
  1197. X ***************************************************************************************/
  1198. XTVeosErr MyModule_LoadMyPrims()
  1199. X{
  1200. X    DEFINE_SUBR( "ROLLOVER", Tricks1_RollOver )        
  1201. X    DEFINE_SUBR( "PLAYDEAD", Tricks2_PlayDead )     
  1202. X    DEFINE_SUBR( "FETCH", Tricks3_Fetch )           
  1203. X    DEFINE_SUBR( "GONUTS", Tricks4_GoNuts )         
  1204. X                                                    
  1205. X    DEFINE_FSUBR( "REPEAT", Tricks5_Repeat )        
  1206. X       
  1207. X    /** NOTES:
  1208. X     **
  1209. X     ** No semicolon is necessary after these macros.
  1210. X     ** This is to preserve compatibility with another xlisp
  1211. X     ** mechanism for including user-defined functions.
  1212. X     **
  1213. X     ** First arg is name you want prim to be in lisp, use all CAPS.
  1214. X     ** Second arg is actual C function, must return an LVAL.
  1215. X     ** Use DEFINE_FSUBR for lisp special forms.
  1216. X     ** Most likely you wont need them.
  1217. X     **/
  1218. X
  1219. X    return(VEOS_SUCCESS);
  1220. X    }
  1221. X/***************************************************************************************/
  1222. X
  1223. X
  1224. X3. Compile your main and primitives and link with the options:
  1225. X
  1226. X   -L/home/veos/lib/
  1227. X   -lxlisp -lxvnative_glue -lkernel
  1228. X
  1229. X   See VEOS kernel makefile for example build sequence.
  1230. X   Don't forget to link to the software packages which contain included primitives.
  1231. X   Notice that the kernel and the kernel interface to lisp are separate libraries.
  1232. X
  1233. X
  1234. X4. Now you have a stand-alone entity.  This entity should behave just like the
  1235. X   base-level entity for application-nonspecific tasks, ie. standard lisp.
  1236. END_OF_FILE
  1237. if test 41783 -ne `wc -c <'docs/VEOS_The_Complete_Documentation'`; then
  1238.     echo shar: \"'docs/VEOS_The_Complete_Documentation'\" unpacked with wrong size!
  1239. fi
  1240. # end of 'docs/VEOS_The_Complete_Documentation'
  1241. fi
  1242. if test -f 'src/kernel_current/shell/xv_glutils.c' -a "${1}" != "-c" ; then 
  1243.   echo shar: Will not clobber existing file \"'src/kernel_current/shell/xv_glutils.c'\"
  1244. else
  1245. echo shar: Extracting \"'src/kernel_current/shell/xv_glutils.c'\" \(43094 characters\)
  1246. sed "s/^X//" >'src/kernel_current/shell/xv_glutils.c' <<'END_OF_FILE'
  1247. X/****************************************************************************************
  1248. X *                                            *
  1249. X * file: xv_glutils.c                                    *
  1250. X *                                            *
  1251. X * Sundry utilities which serve as glue for xlisp veos primitives.            *
  1252. X *                                            *
  1253. X * creation: April 13, 1992                                *
  1254. X *                                            *
  1255. X *                                            *
  1256. X * by Geoffrey P. Coco at the HITLab, Seattle.                          *
  1257. X *                                            *
  1258. X ****************************************************************************************/
  1259. X
  1260. X
  1261. X/****************************************************************************************
  1262. X * Copyright (C) 1992  Geoffrey P. Coco, Human Interface Technology Lab, Seattle    *
  1263. X ****************************************************************************************/
  1264. X
  1265. X
  1266. X
  1267. X/****************************************************************************************
  1268. X *                          preliminaries                    */
  1269. X
  1270. X#include <math.h>
  1271. X#include "xlisp.h"
  1272. X
  1273. X/* VEOS definitions: */
  1274. X#include "kernel.h"
  1275. X
  1276. X#define NATIVE_CODE
  1277. X#include "xv_native.h"
  1278. X#undef NATIVE_CODE
  1279. X
  1280. X/****************************************************************************************/
  1281. X
  1282. Xextern LVAL     xsendmsg0();
  1283. Xextern LVAL    s_unbound;
  1284. Xextern LVAL    true;
  1285. Xextern LVAL     xlfatal();
  1286. X
  1287. X/****************************************************************************************/
  1288. X
  1289. Xboolean        native_bSubstBeenMarked;
  1290. Xboolean        native_bVoidBeenMarked;
  1291. Xboolean        native_bDestruct;
  1292. X
  1293. X#define SUBST    native_bSubstBeenMarked
  1294. X#define VOID    native_bVoidBeenMarked
  1295. X#define MOD    native_bDestruct
  1296. X
  1297. X/****************************************************************************************/
  1298. X
  1299. XTVeosErr Native_PatVEltClerical();
  1300. Xextern LVAL ReverseList();
  1301. X
  1302. X/****************************************************************************************/
  1303. X
  1304. X
  1305. X
  1306. X
  1307. X/****************************************************************************************
  1308. X                Basic Xlisp <--> Nancy Conversion
  1309. X ****************************************************************************************/
  1310. X
  1311. X
  1312. X/****************************************************************************************/
  1313. XTVeosErr Native_XEltToVElt(pXElt, pVElt)
  1314. X    LVAL     pXElt;
  1315. X    TPElt    pVElt;
  1316. X{
  1317. X    TVeosErr    iErr;
  1318. X
  1319. X    iErr = VEOS_FAILURE;
  1320. X
  1321. X
  1322. X    /** NIL is the empty grouple **/
  1323. X
  1324. X    if (null(pXElt)) {
  1325. X    iErr = Nancy_NewGrouple(&pVElt->u.pGr);
  1326. X    pVElt->iType = GR_grouple;
  1327. X    }
  1328. X
  1329. X
  1330. X    /** case-wise conversion to nancy format **/
  1331. X
  1332. X    else {
  1333. X    switch (ntype(pXElt)) {
  1334. X
  1335. X    case CONS:
  1336. X        /** a list becomes a grouple **/
  1337. X        iErr = Native_ListToGrouple(pXElt, &pVElt->u.pGr);
  1338. X        pVElt->iType = GR_grouple;
  1339. X        break;
  1340. X        
  1341. X    case VECTOR:
  1342. X        /** a vector becomes a special grouple **/
  1343. X        iErr = Native_VectToGrouple(pXElt, &pVElt->u.pGr);
  1344. X        pVElt->iType = GR_vector;
  1345. X        break;
  1346. X
  1347. X    case FIXNUM:
  1348. X        pVElt->iType = GR_int;
  1349. X        pVElt->u.iVal = getfixnum(pXElt);
  1350. X        break;
  1351. X        
  1352. X    case FLONUM:
  1353. X        pVElt->iType = GR_float;
  1354. X        pVElt->u.fVal = (float) getflonum(pXElt);
  1355. X        break;
  1356. X        
  1357. X    case STRING:
  1358. X        pVElt->iType = GR_string;
  1359. X        pVElt->u.pS = strdup((char *) getstring(pXElt));
  1360. X        break;
  1361. X        
  1362. X    case SYMBOL:
  1363. X        pVElt->iType = GR_prim;
  1364. X        pVElt->u.pS = strdup(getstring(getpname(pXElt)));
  1365. X        break;
  1366. X        
  1367. X    default:
  1368. X        iErr = NATIVE_BADVTYPE;
  1369. X        break;
  1370. X
  1371. X        }
  1372. X    }
  1373. X
  1374. X    return(iErr);
  1375. X
  1376. X    } /* Native_XEltToVElt */
  1377. X/****************************************************************************************/
  1378. X
  1379. X
  1380. X
  1381. X/****************************************************************************************/
  1382. XTVeosErr Native_ListToGrouple(pList, hGrouple)
  1383. X    LVAL    pList;
  1384. X    THGrouple    hGrouple;
  1385. X{
  1386. X    TVeosErr    iErr;
  1387. X    LVAL    pXFinger;
  1388. X    int        iElt;
  1389. X    TPGrouple    pGrouple;
  1390. X    TPElt    pVFinger;
  1391. X
  1392. X    
  1393. X    *hGrouple = nil;
  1394. X
  1395. X    iErr = Nancy_NewGrouple(&pGrouple);
  1396. X    iElt = 0;
  1397. X
  1398. X    /** convert each lisp sub-element **/
  1399. X
  1400. X    pXFinger = pList;
  1401. X    while (!null(pXFinger) && iErr == VEOS_SUCCESS) {
  1402. X
  1403. X
  1404. X    /** make room for another grouple element **/
  1405. X    
  1406. X    Nancy_NewElementsInGrouple(pGrouple, iElt, 1, GR_unspecified, 0);
  1407. X
  1408. X
  1409. X    /** do actual element conversion **/
  1410. X
  1411. X    iErr = Native_XEltToVElt(car(pXFinger), &pGrouple->pEltList[iElt]);
  1412. X
  1413. X
  1414. X    /** advance element refs **/
  1415. X
  1416. X    iElt ++;
  1417. X    pXFinger = cdr(pXFinger);
  1418. X
  1419. X    } /* while */
  1420. X
  1421. X
  1422. X    if (iErr == VEOS_SUCCESS)
  1423. X    *hGrouple = pGrouple;
  1424. X    else
  1425. X    Nancy_DisposeGrouple(pGrouple);
  1426. X
  1427. X
  1428. X    return(iErr);
  1429. X
  1430. X    } /* Native_ListToGrouple */
  1431. X/****************************************************************************************/
  1432. X
  1433. X
  1434. X
  1435. X/****************************************************************************************/
  1436. XTVeosErr Native_VectToGrouple(pVect, hGrouple)
  1437. X    LVAL    pVect;
  1438. X    THGrouple    hGrouple;
  1439. X{
  1440. X    TVeosErr    iErr;
  1441. X    int        iElts, iEltIndex;
  1442. X    TPGrouple    pGrouple;
  1443. X    TPElt    pVElt;
  1444. X
  1445. X    *hGrouple = nil;
  1446. X
  1447. X    iErr = Nancy_NewGrouple(&pGrouple);
  1448. X
  1449. X
  1450. X    iElts = getsz(pVect);
  1451. X    if (iElts > 0 && iErr == VEOS_SUCCESS) {
  1452. X
  1453. X    /** make enough room for all impending elements **/
  1454. X
  1455. X    iErr = Nancy_NewElementsInGrouple(pGrouple, 0, iElts, GR_unspecified, 0);
  1456. X
  1457. X
  1458. X
  1459. X    /** convert each lisp sub-element **/
  1460. X
  1461. X    iEltIndex = 0; pVElt = pGrouple->pEltList;
  1462. X    while (iEltIndex < iElts && iErr == VEOS_SUCCESS) {
  1463. X
  1464. X        iErr = Native_XEltToVElt(getelement(pVect, iEltIndex), pVElt);
  1465. X
  1466. X        iEltIndex ++; pVElt ++;
  1467. X        }
  1468. X    }
  1469. X
  1470. X    if (iErr == VEOS_SUCCESS)
  1471. X    *hGrouple = pGrouple;
  1472. X    else
  1473. X    Nancy_DisposeGrouple(pGrouple);
  1474. X
  1475. X
  1476. X    return(iErr);
  1477. X
  1478. X    } /* Native_VectToGrouple */
  1479. X/****************************************************************************************/
  1480. X
  1481. X
  1482. X
  1483. X/****************************************************************************************/
  1484. XTVeosErr Native_VEltToXElt(pVElt, hXElt)
  1485. X    TPElt    pVElt;
  1486. X    LVAL     *hXElt;
  1487. X{
  1488. X    TVeosErr    iErr;
  1489. X
  1490. X
  1491. X    *hXElt = NIL;
  1492. X
  1493. X    iErr = VEOS_SUCCESS;
  1494. X
  1495. X    switch (pVElt->iType) {
  1496. X
  1497. X    case GR_grouple:
  1498. X    iErr = Native_GroupleToList(pVElt->u.pGr, hXElt);
  1499. X    break;
  1500. X    
  1501. X    case GR_vector:
  1502. X    iErr = Native_GroupleToVect(pVElt->u.pGr, hXElt);
  1503. X    break;
  1504. X
  1505. X    case GR_int:            
  1506. X    *hXElt = cvfixnum(pVElt->u.iVal);
  1507. X    break;
  1508. X    
  1509. X    case GR_float:
  1510. X    *hXElt = cvflonum(pVElt->u.fVal);
  1511. X    break;
  1512. X    
  1513. X    case GR_string:
  1514. X    *hXElt = cvstring(pVElt->u.pS);
  1515. X    break;
  1516. X    
  1517. X    case GR_prim:
  1518. X    *hXElt = xlenter(pVElt->u.pS);
  1519. X    break;
  1520. X
  1521. X    case GR_unspecified:
  1522. X    iErr = NATIVE_EMPTYELT;
  1523. X    break;
  1524. X
  1525. X    default:    
  1526. X    iErr = NATIVE_BADXTYPE;
  1527. X    break;
  1528. X
  1529. X    }
  1530. X
  1531. X    return(iErr);
  1532. X
  1533. X    } /* Native_VEltToXElt */
  1534. X/****************************************************************************************/
  1535. X
  1536. X
  1537. X
  1538. X/****************************************************************************************/
  1539. XTVeosErr Native_GroupleToList(pGrouple, hList)
  1540. X    TPGrouple    pGrouple;
  1541. X    LVAL    *hList;
  1542. X{
  1543. X    TVeosErr    iErr;
  1544. X    LVAL    pNewXElt, pList;
  1545. X    int        iElts, iElt;
  1546. X
  1547. X    xlstkcheck(2);
  1548. X    xlsave(pNewXElt);
  1549. X    xlsave(pList);
  1550. X
  1551. X    iErr = VEOS_SUCCESS;
  1552. X    iElts = pGrouple->iElts;
  1553. X    iElt = iElts - 1;
  1554. X
  1555. X    while (iElt >= 0 && iErr == VEOS_SUCCESS) {
  1556. X    
  1557. X    iErr = Native_VEltToXElt(&pGrouple->pEltList[iElt], &pNewXElt);
  1558. X    if (iErr == VEOS_SUCCESS)
  1559. X        pList = cons(pNewXElt, pList);
  1560. X
  1561. X    iElt --;
  1562. X    }
  1563. X
  1564. X    *hList = pList;
  1565. X
  1566. X    xlpopn(2);
  1567. X
  1568. X    return(iErr);
  1569. X
  1570. X    } /* Native_GroupleToList */
  1571. X/****************************************************************************************/
  1572. X
  1573. X
  1574. X
  1575. X/****************************************************************************************/
  1576. XTVeosErr Native_GroupleToVect(pGrouple, hVect)
  1577. X    TPGrouple    pGrouple;
  1578. X    LVAL    *hVect;
  1579. X{
  1580. X    TVeosErr    iErr;
  1581. X    LVAL    pNewXElt, pVect;
  1582. X    int        iElts, iElt;
  1583. X
  1584. X    xlstkcheck(2);
  1585. X    xlsave(pVect);
  1586. X    xlsave(pNewXElt);
  1587. X
  1588. X    iErr = VEOS_SUCCESS;
  1589. X    iElts = pGrouple->iElts;
  1590. X    iElt = 0;
  1591. X
  1592. X    pVect = newvector(iElts);
  1593. X
  1594. X    while (iElt < iElts && iErr == VEOS_SUCCESS) {
  1595. X    
  1596. X    iErr = Native_VEltToXElt(&pGrouple->pEltList[iElt], &pNewXElt);
  1597. X    if (iErr == VEOS_SUCCESS)
  1598. X        setelement(pVect, iElt, pNewXElt);
  1599. X
  1600. X    iElt ++;
  1601. X    }
  1602. X
  1603. X    *hVect = pVect;
  1604. X
  1605. X    xlpopn(2);
  1606. X
  1607. X    return(iErr);
  1608. X
  1609. X    } /* Native_GroupleToVect */
  1610. X/****************************************************************************************/
  1611. X
  1612. X
  1613. X
  1614. X/****************************************************************************************
  1615. X             Timestamped Xlisp <--> Nancy Conversion
  1616. X ****************************************************************************************/
  1617. X
  1618. X/****************************************************************************************/
  1619. XTVeosErr Native_NewVEltToXElt(pVElt, hXElt, time)
  1620. X    TPElt    pVElt;
  1621. X    LVAL     *hXElt;
  1622. X    TTimeStamp    time;
  1623. X{
  1624. X    TVeosErr    iErr;
  1625. X
  1626. X    *hXElt = NIL;
  1627. X    iErr = NATIVE_STALE;
  1628. X
  1629. X    if (TIME_LESS_THAN(pVElt->tLastMod, time)) {
  1630. X
  1631. X    /** old data, retrieve only contents of containers 
  1632. X     **/
  1633. X    if (pVElt->iType == GR_grouple)
  1634. X        iErr = Native_NewGroupleToList(pVElt->u.pGr, hXElt, time);
  1635. X    
  1636. X    else if (pVElt->iType == GR_vector)
  1637. X        iErr = Native_NewGroupleToVect(pVElt->u.pGr, hXElt, time);
  1638. X    }
  1639. X
  1640. X    else {
  1641. X    /** new data, retrieve completely **/
  1642. X
  1643. X    switch (pVElt->iType) {
  1644. X        
  1645. X    case GR_grouple:            
  1646. X        iErr = Native_GroupleToList(pVElt->u.pGr, hXElt);
  1647. X        break;
  1648. X
  1649. X    case GR_vector:            
  1650. X        iErr = Native_GroupleToVect(pVElt->u.pGr, hXElt);
  1651. X        break;
  1652. X
  1653. X    case GR_int:            
  1654. X        *hXElt = cvfixnum(pVElt->u.iVal);
  1655. X        iErr = VEOS_SUCCESS;
  1656. X        break;
  1657. X        
  1658. X    case GR_float:
  1659. X        *hXElt = cvflonum(pVElt->u.fVal);
  1660. X        iErr = VEOS_SUCCESS;
  1661. X        break;
  1662. X        
  1663. X    case GR_string:
  1664. X        *hXElt = cvstring(pVElt->u.pS);
  1665. X        iErr = VEOS_SUCCESS;
  1666. X        break;
  1667. X        
  1668. X    case GR_prim:
  1669. X        *hXElt = xlenter(pVElt->u.pS);
  1670. X        iErr = VEOS_SUCCESS;
  1671. X        break;
  1672. X        
  1673. X    case GR_unspecified:
  1674. X        iErr = NATIVE_EMPTYELT;
  1675. X        break;
  1676. X        
  1677. X    default:    
  1678. X        iErr = NATIVE_BADXTYPE;
  1679. X        break;
  1680. X        
  1681. X        }
  1682. X    }
  1683. X
  1684. X    return(iErr);
  1685. X
  1686. X    } /* Native_NewVEltToXElt */
  1687. X/****************************************************************************************/
  1688. X
  1689. X
  1690. X
  1691. X/****************************************************************************************/
  1692. XTVeosErr Native_NewGroupleToList(pGrouple, hList, time)
  1693. X    TPGrouple    pGrouple;
  1694. X    LVAL    *hList;
  1695. X    TTimeStamp    time;
  1696. X{
  1697. X    TVeosErr    iErr = VEOS_SUCCESS;
  1698. X    LVAL    pNewXElt, pList;
  1699. X    int        iElts, iElt;
  1700. X    TPElt    pVElt;
  1701. X    boolean    bStale = TRUE;
  1702. X
  1703. X    xlsave1(pNewXElt);
  1704. X    xlsave1(pList);
  1705. X
  1706. X    iElts = pGrouple->iElts;
  1707. X    iElt = iElts - 1;
  1708. X
  1709. X    while (iElt >= 0) {
  1710. X    
  1711. X    /** determine if caller has already seen this data **/
  1712. X    
  1713. X    iErr = Native_NewVEltToXElt(&pGrouple->pEltList[iElt], &pNewXElt, time);
  1714. X    if (iErr == VEOS_SUCCESS) {
  1715. X        /** assume caller has locked this ptr **/
  1716. X
  1717. X        pList = cons(pNewXElt, pList);
  1718. X        bStale = FALSE;
  1719. X        }
  1720. X
  1721. X    else if (iErr == NATIVE_STALE)
  1722. X        iErr = VEOS_SUCCESS;
  1723. X
  1724. X    else
  1725. X        break;
  1726. X
  1727. X    iElt --;
  1728. X    }
  1729. X
  1730. X    if (iErr == VEOS_SUCCESS) {
  1731. X    if (bStale)
  1732. X        iErr = NATIVE_STALE;
  1733. X
  1734. X    *hList = pList;
  1735. X    }
  1736. X
  1737. X    xlpopn(2);
  1738. X
  1739. X    return(iErr);
  1740. X
  1741. X    } /* Native_NewGroupleToList */
  1742. X/****************************************************************************************/
  1743. X
  1744. X
  1745. X
  1746. X/****************************************************************************************/
  1747. XTVeosErr Native_NewGroupleToVect(pGrouple, hVect, time)
  1748. X    TPGrouple    pGrouple;
  1749. X    LVAL    *hVect;
  1750. X    TTimeStamp    time;
  1751. X{
  1752. X    TVeosErr    iErr = VEOS_SUCCESS;
  1753. X    LVAL    pNewXElt, pVect;
  1754. X    int        iElts, iElt;
  1755. X    boolean    bStale = TRUE;
  1756. X
  1757. X    xlsave1(pNewXElt);
  1758. X    xlsave1(pVect);
  1759. X
  1760. X    iElts = pGrouple->iElts;
  1761. X    pVect = newvector(iElts);
  1762. X
  1763. X    iElt = 0;
  1764. X
  1765. X    while (iElt < iElts) {
  1766. X    
  1767. X    iErr = Native_NewVEltToXElt(&pGrouple->pEltList[iElt], &pNewXElt, time);
  1768. X    if (iErr == VEOS_SUCCESS) {
  1769. X
  1770. X        /** assume caller has locked this ptr **/
  1771. X
  1772. X        setelement(pVect, iElt, pNewXElt);
  1773. X        bStale = FALSE;
  1774. X        }
  1775. X
  1776. X    else if (iErr == NATIVE_STALE)
  1777. X        iErr = VEOS_SUCCESS;
  1778. X
  1779. X    else
  1780. X        break;
  1781. X
  1782. X    iElt ++;
  1783. X    }
  1784. X
  1785. X    if (iErr == VEOS_SUCCESS) {
  1786. X    if (bStale)
  1787. X        iErr = NATIVE_STALE;
  1788. X    
  1789. X    *hVect = pVect;
  1790. X    }
  1791. X
  1792. X    xlpopn(2);
  1793. X
  1794. X    return(iErr);
  1795. X
  1796. X    } /* Native_NewGroupleToVect */
  1797. X/****************************************************************************************/
  1798. X
  1799. X
  1800. X
  1801. X/****************************************************************************************/
  1802. XTVeosErr Native_XEltToNewVElt(pXElt, pVElt, time)
  1803. X    LVAL     pXElt;
  1804. X    TPElt    pVElt;
  1805. X    TTimeStamp    time;
  1806. X{
  1807. X    TVeosErr    iErr;
  1808. X
  1809. X    iErr = VEOS_SUCCESS;
  1810. X
  1811. X
  1812. X    /** NIL is the empty grouple **/
  1813. X
  1814. X    if (null(pXElt)) {
  1815. X    pVElt->iType = GR_grouple;
  1816. X    iErr = Nancy_NewGrouple(&pVElt->u.pGr);
  1817. X    }
  1818. X
  1819. X    /** case-wise conversion to nancy format **/
  1820. X
  1821. X    else {
  1822. X    switch (ntype(pXElt)) {
  1823. X
  1824. X    case CONS:
  1825. X        /** a list becomes a grouple **/
  1826. X        iErr = Native_ListToNewGrouple(pXElt, &pVElt->u.pGr, time);
  1827. X        pVElt->iType = GR_grouple;
  1828. X        break;
  1829. X        
  1830. X    case VECTOR:
  1831. X        /** a vector becomes a special grouple **/
  1832. X        iErr = Native_VectToNewGrouple(pXElt, &pVElt->u.pGr, time);
  1833. X        pVElt->iType = GR_vector;
  1834. X        break;
  1835. X
  1836. X    case FIXNUM:
  1837. X        pVElt->iType = GR_int;
  1838. X        pVElt->u.iVal = getfixnum(pXElt);
  1839. X        break;
  1840. X        
  1841. X    case FLONUM:
  1842. X        pVElt->iType = GR_float;
  1843. X        pVElt->u.fVal = (float) getflonum(pXElt);
  1844. X        break;
  1845. X        
  1846. X    case STRING:
  1847. X        pVElt->iType = GR_string;
  1848. X        pVElt->u.pS = strdup((char *) getstring(pXElt));
  1849. X        break;
  1850. X        
  1851. X    case SYMBOL:
  1852. X        pVElt->iType = GR_prim;
  1853. X        pVElt->u.pS = strdup(getstring(getpname(pXElt)));
  1854. X        break;
  1855. X        
  1856. X    default:
  1857. X        iErr = NATIVE_BADVTYPE;
  1858. X        break;
  1859. X
  1860. X        }
  1861. X    }
  1862. X
  1863. X    pVElt->tLastMod = time;
  1864. X
  1865. X    return(iErr);
  1866. X
  1867. X    } /* Native_XEltToNewVElt */
  1868. X/****************************************************************************************/
  1869. X
  1870. X
  1871. X
  1872. X/****************************************************************************************/
  1873. XTVeosErr Native_ListToNewGrouple(pList, hGrouple, time)
  1874. X    LVAL    pList;
  1875. X    THGrouple    hGrouple;
  1876. X    TTimeStamp    time;
  1877. X{
  1878. X    TVeosErr    iErr;
  1879. X    LVAL    pXFinger;
  1880. X    int        iElt;
  1881. X    TPGrouple    pGrouple;
  1882. X    TPElt    pVFinger;
  1883. X
  1884. X    xlsave1(pXFinger);
  1885. X    
  1886. X    *hGrouple = nil;
  1887. X
  1888. X    iErr = Nancy_NewGrouple(&pGrouple);
  1889. X    iElt = 0;
  1890. X
  1891. X
  1892. X    /** convert each lisp sub-element **/
  1893. X
  1894. X    pXFinger = pList;
  1895. X    while (!null(pXFinger) && iErr == VEOS_SUCCESS) {
  1896. X
  1897. X
  1898. X    /** make room for another grouple element **/
  1899. X    
  1900. X    Nancy_NewElementsInGrouple(pGrouple, iElt, 1, GR_unspecified, 0);
  1901. X
  1902. X
  1903. X    /** do actual element conversion **/
  1904. X
  1905. X    iErr = Native_XEltToNewVElt(car(pXFinger), &pGrouple->pEltList[iElt], time);
  1906. X
  1907. X
  1908. X    /** advance element refs **/
  1909. X
  1910. X    iElt ++;
  1911. X    pXFinger = cdr(pXFinger);
  1912. X
  1913. X    } /* while */
  1914. X
  1915. X
  1916. X    if (iErr == VEOS_SUCCESS)
  1917. X    *hGrouple = pGrouple;
  1918. X    else
  1919. X    Nancy_DisposeGrouple(pGrouple);
  1920. X
  1921. X    xlpop();
  1922. X
  1923. X    return(iErr);
  1924. X
  1925. X    } /* Native_ListToNewGrouple */
  1926. X/****************************************************************************************/
  1927. X
  1928. X
  1929. X
  1930. X/****************************************************************************************/
  1931. XTVeosErr Native_VectToNewGrouple(pVect, hGrouple, time)
  1932. X    LVAL    pVect;
  1933. X    THGrouple    hGrouple;
  1934. X    TTimeStamp    time;
  1935. X{
  1936. X    TVeosErr    iErr;
  1937. X    int        iElts, iEltIndex;
  1938. X    TPGrouple    pGrouple;
  1939. X
  1940. X
  1941. X    *hGrouple = nil;
  1942. X
  1943. X    iErr = Nancy_NewGrouple(&pGrouple);
  1944. X
  1945. X
  1946. X    iElts = getsz(pVect);
  1947. X    if (iElts > 0 && iErr == VEOS_SUCCESS) {
  1948. X
  1949. X    /** make enough room for all impending elements **/
  1950. X
  1951. X    iErr = Nancy_NewElementsInGrouple(pGrouple, 0, iElts, GR_unspecified, 0);
  1952. X
  1953. X
  1954. X
  1955. X    /** convert each lisp sub-element **/
  1956. X
  1957. X    iEltIndex = 0;
  1958. X    while (iEltIndex < iElts && iErr == VEOS_SUCCESS) {
  1959. X
  1960. X        iErr = Native_XEltToNewVElt(getelement(pVect, iEltIndex),
  1961. X                    &pGrouple->pEltList[iEltIndex], time);
  1962. X        iEltIndex ++;
  1963. X        }
  1964. X    }
  1965. X
  1966. X    if (iErr == VEOS_SUCCESS)
  1967. X    *hGrouple = pGrouple;
  1968. X    else
  1969. X    Nancy_DisposeGrouple(pGrouple);
  1970. X
  1971. X
  1972. X    return(iErr);
  1973. X
  1974. X    } /* Native_VectToNewGrouple */
  1975. X/****************************************************************************************/
  1976. X
  1977. X
  1978. X/****************************************************************************************
  1979. X               Pattern Xlisp <--> Nancy Conversion
  1980. X ****************************************************************************************/
  1981. X
  1982. X
  1983. X/****************************************************************************************/
  1984. XTVeosErr Native_GetPatternArg(hPattern, iMatchFlag)
  1985. X    THGrouple    hPattern;
  1986. X    int        iMatchFlag;
  1987. X{    
  1988. X    LVAL    pXElt;
  1989. X    TVeosErr    iErr;
  1990. X
  1991. X
  1992. X    SUBST = FALSE;
  1993. X    VOID = FALSE;
  1994. X    MOD = (iMatchFlag == NANCY_ReplaceMatch);
  1995. X
  1996. X
  1997. X    /** get lisp pattern list **/
  1998. X
  1999. X    pXElt = xlgalist();
  2000. X
  2001. X
  2002. X    /** dispatch lisp->veos conversion **/
  2003. X
  2004. X    iErr = Native_PatListToGrouple(pXElt, hPattern);
  2005. X
  2006. X#ifndef OPTIMAL
  2007. X    if (iErr == VEOS_SUCCESS) {
  2008. X    if (iMatchFlag == NANCY_ReplaceMatch) {
  2009. X        if (!SUBST && !VOID)
  2010. X        iErr = NATIVE_NOREPLACEMARK;
  2011. X        }
  2012. X    else {
  2013. X        if (VOID)
  2014. X        iErr = NATIVE_NOVOID;
  2015. X        else if (!SUBST)
  2016. X        iErr = NATIVE_NOFETCHMARK;
  2017. X        }
  2018. X    }
  2019. X#endif
  2020. X
  2021. X    return(iErr);
  2022. X
  2023. X    } /* Native_GetPatternArg */
  2024. X/****************************************************************************************/
  2025. X
  2026. X
  2027. X
  2028. X/****************************************************************************************/
  2029. XTVeosErr Native_PatXEltToVElt(pXElt, pVElt)
  2030. X    LVAL     pXElt;
  2031. X    TPElt    pVElt;
  2032. X{
  2033. X    TVeosErr    iErr;
  2034. X
  2035. X    iErr = VEOS_SUCCESS;
  2036. X
  2037. X
  2038. X    /** NIL is the empty grouple **/
  2039. X
  2040. X    if (null(pXElt)) {
  2041. X    iErr = Nancy_NewGrouple(&pVElt->u.pGr);
  2042. X    pVElt->iType = GR_grouple;
  2043. X    }
  2044. X
  2045. X
  2046. X    /** case-wise conversion to nancy format **/
  2047. X
  2048. X    else {
  2049. X    switch (ntype(pXElt)) {
  2050. X
  2051. X    case CONS:
  2052. X        /** a list becomes a grouple **/
  2053. X        iErr = Native_PatListToGrouple(pXElt, &pVElt->u.pGr);
  2054. X        pVElt->iType = GR_grouple;
  2055. X        break;
  2056. X        
  2057. X    case VECTOR:
  2058. X        /** a vector becomes a special grouple **/
  2059. X        iErr = Native_PatVectToGrouple(pXElt, &pVElt->u.pGr);
  2060. X        pVElt->iType = GR_vector;
  2061. X        break;
  2062. X
  2063. X    case FIXNUM:
  2064. X        pVElt->iType = GR_int;
  2065. X        pVElt->u.iVal = getfixnum(pXElt);
  2066. X        break;
  2067. X        
  2068. X    case FLONUM:
  2069. X        pVElt->iType = GR_float;
  2070. X        pVElt->u.fVal = (float) getflonum(pXElt);
  2071. X        break;
  2072. X        
  2073. X    case STRING:
  2074. X        pVElt->iType = GR_string;
  2075. X        pVElt->u.pS = strdup((char *) getstring(pXElt));
  2076. X        break;
  2077. X        
  2078. X    case SYMBOL:
  2079. X        iErr = Native_ConvertSymbol(pXElt, pVElt);
  2080. X        break;
  2081. X        
  2082. X    default:
  2083. X        iErr = NATIVE_BADVTYPE;
  2084. X        break;
  2085. X        }
  2086. X    }
  2087. X
  2088. X    return(iErr);
  2089. X
  2090. X    } /* Native_PatXEltToVElt */
  2091. X/****************************************************************************************/
  2092. X
  2093. X
  2094. X
  2095. X/****************************************************************************************/
  2096. XTVeosErr Native_PatListToGrouple(pList, hGrouple)
  2097. X    LVAL    pList;
  2098. X    THGrouple    hGrouple;
  2099. X{
  2100. X    TVeosErr    iErr;
  2101. X    LVAL    pXFinger;
  2102. X    int        iElt;
  2103. X    TPGrouple    pGrouple;
  2104. X    TPElt    pVFinger;
  2105. X    TPatStatRec    patPB;
  2106. X    TElt    eltNew;
  2107. X
  2108. X    
  2109. X    /******************
  2110. X     ** setup locals **
  2111. X     ******************/
  2112. X
  2113. X    *hGrouple = nil;
  2114. X    iErr = Nancy_NewGrouple(&pGrouple);
  2115. X
  2116. X    /** by default, a grouple is literally an ordered list of elements.
  2117. X     **    in some cases, a pattern grouple can specifiy an order-blind element
  2118. X     ** collection.  in other words, a content-dependent-pattern.
  2119. X     **/
  2120. X    patPB.bOrdered = TRUE;
  2121. X
  2122. X    /** prepare to check for pattern format inconsistencies **/
  2123. X
  2124. X    patPB.bExpContent = FALSE;
  2125. X    patPB.bExpOrder = FALSE;
  2126. X    patPB.bMarkedWithin = FALSE;
  2127. X    patPB.bTouchedWithin = FALSE;
  2128. X    
  2129. X    patPB.bMarkNextElt = FALSE;
  2130. X    patPB.bTouchNextElt = FALSE;
  2131. X    patPB.bMustEnd = FALSE;
  2132. X    patPB.bGetAnother = FALSE;
  2133. X
  2134. X
  2135. X    /***********************************
  2136. X     ** convert each lisp sub-element **
  2137. X     ***********************************/
  2138. X
  2139. X    pXFinger = pList;
  2140. X    while (!null(pXFinger)) {
  2141. X
  2142. X    eltNew = NIL_ELT;
  2143. X
  2144. X    /** do actual element conversion **/
  2145. X    
  2146. X    iErr = Native_PatXEltToVElt(car(pXFinger), &eltNew);
  2147. X    if (iErr != VEOS_SUCCESS)
  2148. X        break;
  2149. X    
  2150. X    iErr = Native_PatVEltClerical(&eltNew, &patPB);
  2151. X    if (iErr != VEOS_SUCCESS)
  2152. X        break;
  2153. X    
  2154. X    if (patPB.bGetAnother) {
  2155. X        
  2156. X        /** this elt was actually a modifier elt for next one.
  2157. X         ** prepare for caller forgetting to pass next elt
  2158. X         **/
  2159. X        iErr = NATIVE_NOTEND;
  2160. X        }
  2161. X    
  2162. X    else {
  2163. X        /** place converted nancy element into dest grouple **/
  2164. X        
  2165. X        Nancy_NewElementsInGrouple(pGrouple, pGrouple->iElts,
  2166. X                       1, GR_unspecified, 0);
  2167. X        pGrouple->pEltList[pGrouple->iElts - 1] = eltNew;
  2168. X        }        
  2169. X    
  2170. X    
  2171. X    /** advance element refs **/
  2172. X    
  2173. X    pXFinger = cdr(pXFinger);
  2174. X    } /* while */
  2175. X
  2176. X    if (iErr != VEOS_SUCCESS)
  2177. X    Nancy_DisposeGrouple(pGrouple);
  2178. X
  2179. X    else {
  2180. X    if (!patPB.bOrdered)
  2181. X        SETFLAG(NANCY_ContentMask, pGrouple->iFlags);
  2182. X    if (patPB.bMarkedWithin)
  2183. X        SETFLAG(NANCY_MarkWithinMask, pGrouple->iFlags);
  2184. X    if (patPB.bTouchedWithin)
  2185. X        SETFLAG(NANCY_TouchWithinMask, pGrouple->iFlags);
  2186. X
  2187. X    *hGrouple = pGrouple;
  2188. X    }
  2189. X
  2190. X    return(iErr);
  2191. X
  2192. X    } /* Native_PatListToGrouple */
  2193. X/****************************************************************************************/
  2194. X
  2195. X
  2196. X
  2197. X/****************************************************************************************/
  2198. XTVeosErr Native_PatVectToGrouple(pVect, hGrouple)
  2199. X    LVAL    pVect;
  2200. X    THGrouple    hGrouple;
  2201. X{
  2202. X    TVeosErr    iErr;
  2203. X    LVAL    pXFinger;
  2204. X    int        iXElts, iXEltIndex;
  2205. X    TPGrouple    pGrouple;
  2206. X    TPatStatRec    patPB;
  2207. X    TElt    eltNew;
  2208. X
  2209. X    /******************
  2210. X     ** setup locals **
  2211. X     ******************/
  2212. X
  2213. X    *hGrouple = nil;
  2214. X    iErr = Nancy_NewGrouple(&pGrouple);
  2215. X
  2216. X    /** by default, a grouple is literally an ordered list of elements.
  2217. X     **    in some cases, a pattern grouple can specifiy an order-blind element
  2218. X     ** collection.  in other words, a content-dependent-pattern.
  2219. X     **/
  2220. X    patPB.bOrdered = TRUE;
  2221. X
  2222. X    /** prepare to check for pattern format inconsistencies **/
  2223. X
  2224. X    patPB.bExpContent = FALSE;
  2225. X    patPB.bExpOrder = FALSE;
  2226. X    patPB.bMarkedWithin = FALSE;
  2227. X    patPB.bTouchedWithin = FALSE;
  2228. X    
  2229. X    patPB.bMarkNextElt = FALSE;
  2230. X    patPB.bTouchNextElt = FALSE;
  2231. X    patPB.bMustEnd = FALSE;
  2232. X    patPB.bGetAnother = FALSE;
  2233. X
  2234. X    iXElts = getsz(pVect);
  2235. X    if (iXElts > 0 && iErr == VEOS_SUCCESS) {
  2236. X
  2237. X    /***********************************
  2238. X     ** convert each lisp sub-element **
  2239. X     ***********************************/
  2240. X    
  2241. X    iXEltIndex = 0;
  2242. X    while (iXEltIndex < iXElts) {
  2243. X        
  2244. X
  2245. X        /** cache current vector element **/
  2246. X        
  2247. X        pXFinger = getelement(pVect, iXEltIndex);
  2248. X        eltNew = NIL_ELT;
  2249. X        
  2250. X        /** do actual element conversion **/
  2251. X        
  2252. X        iErr = Native_PatXEltToVElt(pXFinger, &eltNew);
  2253. X        if (iErr != VEOS_SUCCESS)
  2254. X        break;
  2255. X        
  2256. X        iErr = Native_PatVEltClerical(&eltNew, &patPB);
  2257. X        if (iErr != VEOS_SUCCESS)
  2258. X        break;
  2259. X        
  2260. X        if (patPB.bGetAnother) {
  2261. X
  2262. X        /** this elt was actually a modifier elt for next one.
  2263. X         ** prepare for caller forgetting to pass next elt
  2264. X         **/
  2265. X        iErr = NATIVE_NOTEND;
  2266. X        }
  2267. X
  2268. X        else {
  2269. X        /** place converted nancy element into dest grouple **/
  2270. X        
  2271. X        Nancy_NewElementsInGrouple(pGrouple, pGrouple->iElts,
  2272. X                       1, GR_unspecified, 0);
  2273. X        pGrouple->pEltList[pGrouple->iElts - 1] = eltNew;
  2274. X        }        
  2275. X
  2276. X
  2277. X        /** advance element refs **/
  2278. X        
  2279. X        iXEltIndex ++;
  2280. X
  2281. X        } /* while */
  2282. X    }
  2283. X
  2284. X    if (iErr != VEOS_SUCCESS)
  2285. X    Nancy_DisposeGrouple(pGrouple);
  2286. X
  2287. X    else {
  2288. X    if (!patPB.bOrdered)
  2289. X        SETFLAG(NANCY_ContentMask, pGrouple->iFlags);
  2290. X    if (patPB.bMarkedWithin)
  2291. X        SETFLAG(NANCY_MarkWithinMask, pGrouple->iFlags);
  2292. X    if (patPB.bTouchedWithin)
  2293. X        SETFLAG(NANCY_TouchWithinMask, pGrouple->iFlags);
  2294. X
  2295. X    *hGrouple = pGrouple;
  2296. X    }
  2297. X
  2298. X    return(iErr);
  2299. X
  2300. X    } /* Native_PatVectToGrouple */
  2301. X/****************************************************************************************/
  2302. X
  2303. X
  2304. X
  2305. X/****************************************************************************************/
  2306. XTVeosErr Native_PatVEltClerical(pVElt, pStats)
  2307. X    TPElt        pVElt;
  2308. X    TPPatStatRec    pStats;
  2309. X{
  2310. X    TVeosErr        iErr = VEOS_SUCCESS;
  2311. X
  2312. X#ifndef OPTIMAL
  2313. X    if (pStats->bMustEnd)
  2314. X    iErr = NATIVE_NOTEND;
  2315. X
  2316. X    else {
  2317. X    /** catch possible undefined expressions **/
  2318. X    
  2319. X    switch (pVElt->iType) {
  2320. X        
  2321. X    case GR_these:
  2322. X        if (pStats->bExpContent)
  2323. X        iErr = NATIVE_CANTMIX;
  2324. X        break;
  2325. X        
  2326. X    case GR_theseall:
  2327. X        if (pStats->bExpContent)
  2328. X        iErr = NATIVE_CANTMIX;
  2329. X        break;
  2330. X        
  2331. X    case GR_some:
  2332. X        iErr = NATIVE_NOSTARN;
  2333. X        break;
  2334. X        
  2335. X    case GR_any:
  2336. X        if (pStats->bExpOrder)
  2337. X        iErr = NATIVE_CANTMIX;
  2338. X        break;
  2339. X        
  2340. X    case GR_here:
  2341. X        if (SUBST || VOID) 
  2342. X        iErr = NATIVE_TOOMANYMARKS;
  2343. X        else if (pStats->bGetAnother)
  2344. X        iErr = NATIVE_MODVOID;
  2345. X        break;
  2346. X        
  2347. X    case GR_mark:
  2348. X        if (SUBST || VOID) 
  2349. X        iErr = NATIVE_TOOMANYMARKS;
  2350. X        else if (pStats->bGetAnother)
  2351. X        iErr = NATIVE_THISWHAT;
  2352. X        break;
  2353. X
  2354. X    case GR_touch:
  2355. X        if (!MOD)
  2356. X        iErr = NATIVE_NOTOUCH;
  2357. X        else if (pStats->bGetAnother)
  2358. X        iErr = NATIVE_THISWHAT;
  2359. X        break;
  2360. X
  2361. X    default:
  2362. X        break;
  2363. X        } /* switch */
  2364. X    }
  2365. X#endif    
  2366. X
  2367. X    if (iErr == VEOS_SUCCESS) {
  2368. X
  2369. X    /** mark the element for nancy matcher **/
  2370. X    
  2371. X    if (pStats->bMarkNextElt) {
  2372. X        SETFLAG(NANCY_EltMarkMask, pVElt->iFlags);
  2373. X        pStats->bMarkNextElt = FALSE;
  2374. X        pStats->bGetAnother = FALSE;
  2375. X        }
  2376. X
  2377. X    if (pStats->bTouchNextElt) {
  2378. X        SETFLAG(NANCY_EltTouchMask, pVElt->iFlags);
  2379. X        pStats->bTouchNextElt = FALSE;
  2380. X        pStats->bGetAnother = FALSE;
  2381. X        }
  2382. X
  2383. X
  2384. X    switch (pVElt->iType) {
  2385. X        
  2386. X    case GR_these:
  2387. X        pStats->bExpOrder = TRUE;
  2388. X        break;
  2389. X        
  2390. X    case GR_any:
  2391. X        pStats->bOrdered = FALSE;
  2392. X        pStats->bExpContent = TRUE;
  2393. X        pStats->bMustEnd = TRUE;
  2394. X        break;
  2395. X        
  2396. X    case GR_theseall:
  2397. X        pStats->bExpOrder = TRUE;
  2398. X        pStats->bMustEnd = TRUE;
  2399. X        break;
  2400. X        
  2401. X    case GR_here:
  2402. X        VOID = TRUE;
  2403. X        SETFLAG(NANCY_EltMarkMask, pVElt->iFlags);
  2404. X        pStats->bMarkedWithin = TRUE;
  2405. X        break;
  2406. X        
  2407. X    case GR_mark:
  2408. X        SUBST = TRUE;
  2409. X        pStats->bMarkedWithin = TRUE;
  2410. X        pStats->bMarkNextElt = TRUE;        
  2411. X        pStats->bGetAnother = TRUE;        
  2412. X        break;
  2413. X        
  2414. X    case GR_touch:
  2415. X        pStats->bTouchedWithin = TRUE;
  2416. X        pStats->bTouchNextElt = TRUE;        
  2417. X        pStats->bGetAnother = TRUE;        
  2418. X        break;
  2419. X        
  2420. X    default:
  2421. X        break;
  2422. X        } /* switch */
  2423. X    }
  2424. X
  2425. X    return(iErr);
  2426. X
  2427. X    } /* Native_PatVEltClerical */
  2428. X/****************************************************************************************/
  2429. X
  2430. X
  2431. X
  2432. X/****************************************************************************************/
  2433. XTVeosErr Native_ConvertSymbol(pXElt, pVElt)
  2434. X    LVAL    pXElt;
  2435. X    TPElt    pVElt;
  2436. X{
  2437. X    TVeosErr    iErr = VEOS_SUCCESS;
  2438. X    char    *sSrc;
  2439. X    boolean    bParsed = FALSE;
  2440. X
  2441. X
  2442. X    sSrc = (char *) getstring(getpname(pXElt));
  2443. X
  2444. X    switch(sSrc[0]) {
  2445. X
  2446. X    
  2447. X    case '^':     /* '^' marks the void for insertion */
  2448. X    if (sSrc[1] == '\0') {
  2449. X        pVElt->iType = GR_here;
  2450. X        bParsed = TRUE;
  2451. X        }
  2452. X    break;
  2453. X
  2454. X    case '>':   /* '>' is a mark for the next element */
  2455. X    if (sSrc[1] == '\0') {
  2456. X        pVElt->iType = GR_mark;
  2457. X        bParsed = TRUE;
  2458. X        }
  2459. X    break;
  2460. X
  2461. X    case '~':   /* '~' touches the next element */
  2462. X    if (sSrc[1] == '\0') {
  2463. X        pVElt->iType = GR_touch;
  2464. X        bParsed = TRUE;
  2465. X        }
  2466. X    break;
  2467. X
  2468. X    case '@':     /* '@' is wildcard for ordered elements **/
  2469. X    
  2470. X    /** special form (@) means exactly one element **/
  2471. X    if (sSrc[1] == '\0') {
  2472. X        pVElt->iType = GR_these;
  2473. X        pVElt->u.iVal = 1;
  2474. X        bParsed = TRUE;
  2475. X        }
  2476. X    
  2477. X    /** special form (@n) means exactly n elts **/
  2478. X    else if (IsIntStr(&sSrc[1]) == VEOS_SUCCESS) {
  2479. X        if ((pVElt->u.iVal = atoi(&sSrc[1])) < 1)
  2480. X        iErr = NATIVE_CRAZYWILD;
  2481. X        else
  2482. X        pVElt->iType = GR_these;
  2483. X        bParsed = TRUE;
  2484. X        }
  2485. X    
  2486. X    /** special form (@@) means zero or more elts **/
  2487. X    else if (sSrc[1] == '@' && sSrc[2] == '\0') {
  2488. X        pVElt->iType = GR_theseall;
  2489. X        bParsed = TRUE;
  2490. X        }
  2491. X    break;
  2492. X
  2493. X
  2494. X    case '*':   /* '*' is wildcard for unordered elements */
  2495. X    
  2496. X    /** special form (*) means exatly one element **/
  2497. X    if (sSrc[1] == '\0') {
  2498. X        pVElt->iType = GR_some;
  2499. X        pVElt->u.iVal = 1;
  2500. X        bParsed = TRUE;
  2501. X        }
  2502. X    
  2503. X    /** special form (*n) means exactly n elts **/
  2504. X    else if (IsIntStr(&sSrc[1]) == VEOS_SUCCESS) {
  2505. X        if ((pVElt->u.iVal = atoi(&sSrc[1])) < 1)
  2506. X        iErr = NATIVE_CRAZYWILD;
  2507. X        else
  2508. X        pVElt->iType = GR_some;
  2509. X        bParsed = TRUE;
  2510. X        }
  2511. X    
  2512. X    /** special form (**) means zero or more elts **/
  2513. X    else if (sSrc[1] == '*' && sSrc[2] == '\0') {
  2514. X        pVElt->iType = GR_any;
  2515. X        bParsed = TRUE;
  2516. X        }
  2517. X    break;
  2518. X
  2519. X    } /* switch */
  2520. X
  2521. X
  2522. X    /** save symbol's name as veos prim type **/
  2523. X    
  2524. X    if (!bParsed && iErr == VEOS_SUCCESS) {
  2525. X    pVElt->iType = GR_prim;
  2526. X    pVElt->u.pS = strdup(sSrc);
  2527. X    }
  2528. X    
  2529. X
  2530. X    return(iErr);
  2531. X
  2532. X    } /* Native_ConvertSymbol */
  2533. X/****************************************************************************************/
  2534. X
  2535. X
  2536. X
  2537. X/****************************************************************************************
  2538. X              Xlisp <--> Linearized Data Conversion
  2539. X ****************************************************************************************/
  2540. X
  2541. X
  2542. X/****************************************************************************************/
  2543. XTVeosErr Native_XEltToMsgRec(pXData, pMsgRec)
  2544. X    LVAL         pXData;
  2545. X    TPMsgRec        pMsgRec;
  2546. X{
  2547. X    TVeosErr        iErr;
  2548. X
  2549. X    pMsgRec->iLen = 0;
  2550. X    pMsgRec->sMessage = TALK_BUFFER;
  2551. X
  2552. X
  2553. X    /** perform data conversion to flat network-friendly form **/
  2554. X
  2555. X    iErr = Native_XEltToMessage(pXData, pMsgRec->sMessage, &pMsgRec->iLen);
  2556. X
  2557. X    if (iErr != VEOS_SUCCESS)
  2558. X    Native_TrapErr(iErr, pXData);
  2559. X
  2560. X
  2561. X    return(iErr);
  2562. X
  2563. X    } /* Native_XEltToMsgRec */
  2564. X/****************************************************************************************/
  2565. X
  2566. X
  2567. X
  2568. X/****************************************************************************************/
  2569. XTVeosErr Native_XEltToMessage(pXElt, pBuffer, pLen)
  2570. X    LVAL         pXElt;
  2571. X    char        *pBuffer;
  2572. X    int            *pLen;
  2573. X{
  2574. X    TVeosErr        iErr;
  2575. X    int            iLen;
  2576. X    TF2L        fTrans;
  2577. X
  2578. X    iErr = VEOS_SUCCESS;
  2579. X
  2580. X    /** message element is: element type, then data (except for NIL)
  2581. X     ** assume pBuffer is aligned 
  2582. X     **/
  2583. X
  2584. X    if (null(pXElt)) {
  2585. X
  2586. X    /** nil element is empty grouple **/
  2587. X    *(int *) pBuffer = htonl(GR_grouple);    
  2588. X    pBuffer += 4;
  2589. X
  2590. X    /** empty grouple has zero elements **/
  2591. X    *(int *) pBuffer = htonl(0);    
  2592. X
  2593. X    iLen = 8;
  2594. X    }
  2595. X    else {
  2596. X
  2597. X    switch (ntype(pXElt)) {
  2598. X        
  2599. X    case CONS:
  2600. X        *(int *) pBuffer = htonl(GR_grouple);    
  2601. X        pBuffer += 4;
  2602. X        iLen = 4;
  2603. X        iErr = Native_ListToMessage(pXElt, pBuffer, &iLen);
  2604. X        break;
  2605. X
  2606. X    case VECTOR:
  2607. X        *(int *) pBuffer = htonl(GR_vector);    
  2608. X        pBuffer += 4;
  2609. X        iLen = 4;
  2610. X        iErr = Native_VectToMessage(pXElt, pBuffer, &iLen);
  2611. X        break;
  2612. X
  2613. X    case FIXNUM:
  2614. X        *(int *) pBuffer = htonl(GR_int);    
  2615. X        pBuffer += 4;
  2616. X        *(long *) pBuffer = htonl(getfixnum(pXElt));
  2617. X        iLen = 8;
  2618. X        break;
  2619. X        
  2620. X    case FLONUM:
  2621. X        *(int *) pBuffer = htonl(GR_float);    
  2622. X        pBuffer += 4;
  2623. X        fTrans.u.f = getflonum(pXElt);
  2624. X        *(long *) pBuffer = htonl(fTrans.u.l);
  2625. X        iLen = 8;
  2626. X        break;
  2627. X        
  2628. X    case STRING:
  2629. X        *(int *) pBuffer = htonl(GR_string);    
  2630. X        pBuffer += 4;
  2631. X        strcpy(pBuffer, getstring(pXElt));
  2632. X        iLen = 4 + MEMSIZE(strlen(getstring(pXElt)) + 1);
  2633. X        break;
  2634. X        
  2635. X    case SYMBOL:
  2636. X        *(int *) pBuffer = htonl(GR_prim);    
  2637. X        pBuffer += 4;
  2638. X        strcpy(pBuffer, getstring(getpname(pXElt)));
  2639. X        iLen = 4 + MEMSIZE(strlen(getstring(getpname(pXElt))) + 1);
  2640. X        break;
  2641. X        
  2642. X    default:
  2643. X        iErr = NATIVE_BADVTYPE;
  2644. X        iLen = 0;
  2645. X        break;
  2646. X
  2647. X        } /* switch */
  2648. X    }
  2649. X
  2650. X    *pLen += iLen;
  2651. X
  2652. X    return(iErr);
  2653. X
  2654. X    } /* Native_XEltToMessage */
  2655. X/****************************************************************************************/
  2656. X
  2657. X
  2658. X
  2659. X/****************************************************************************************/
  2660. XTVeosErr Native_ListToMessage(pList, pBuffer, pLen)
  2661. X    LVAL    pList;
  2662. X    char    *pBuffer;
  2663. X    int        *pLen;
  2664. X{
  2665. X    TVeosErr    iErr = VEOS_SUCCESS;
  2666. X    LVAL    pXFinger;
  2667. X    int        iLen, iElts = 0;
  2668. X    char    *pListHead;
  2669. X
  2670. X
  2671. X    /** first code of protocol is number of elements, write later **/
  2672. X    
  2673. X    pListHead = pBuffer;
  2674. X    pBuffer = pListHead + 4;
  2675. X    *pLen += 4;
  2676. X
  2677. X    
  2678. X    /** convert each lisp sub-element **/
  2679. X
  2680. X    pXFinger = pList;
  2681. X    while (!null(pXFinger)) {
  2682. X
  2683. X    /** invoke recursive translation **/
  2684. X
  2685. X    iLen = 0;
  2686. X    iErr = Native_XEltToMessage(car(pXFinger), pBuffer, &iLen);
  2687. X
  2688. X    if (iErr != VEOS_SUCCESS) 
  2689. X        break;
  2690. X
  2691. X    else {
  2692. X        iElts ++;
  2693. X
  2694. X        pBuffer += iLen;
  2695. X        *pLen += iLen;
  2696. X        }
  2697. X
  2698. X    /** advance element ref **/
  2699. X    
  2700. X    pXFinger = cdr(pXFinger);
  2701. X    
  2702. X    } /* while */
  2703. X
  2704. X
  2705. X    /** write number of elements **/
  2706. X
  2707. X    *(int *) pListHead = htonl(iElts);
  2708. X
  2709. X    return(iErr);
  2710. X
  2711. X    } /* Native_ListToMessage */
  2712. X/****************************************************************************************/
  2713. X
  2714. X
  2715. X
  2716. X
  2717. X/****************************************************************************************/
  2718. XTVeosErr Native_VectToMessage(pVect, pBuffer, pLen)
  2719. X    LVAL    pVect;
  2720. X    char    *pBuffer;
  2721. X    int        *pLen;
  2722. X{
  2723. X    TVeosErr    iErr = VEOS_SUCCESS;
  2724. X    LVAL    pXFinger;
  2725. X    int        iLen, iEltIndex, iElts;
  2726. X
  2727. X    iElts = getsz(pVect);
  2728. X
  2729. X    /** first code of protocol is number of elements **/
  2730. X    *(int *) pBuffer = htonl(iElts);
  2731. X
  2732. X    pBuffer += 4;
  2733. X    *pLen += 4;
  2734. X
  2735. X    
  2736. X    /** convert each lisp sub-element **/
  2737. X
  2738. X    iEltIndex = 0;
  2739. X    while(iEltIndex < iElts) {
  2740. X
  2741. X
  2742. X    /** invoke recursive translation **/
  2743. X
  2744. X    iLen = 0;
  2745. X    iErr = Native_XEltToMessage(getelement(pVect, iEltIndex), pBuffer, &iLen);
  2746. X
  2747. X    if (iErr != VEOS_SUCCESS) 
  2748. X        break;
  2749. X
  2750. X    else {
  2751. X        pBuffer += iLen;
  2752. X        *pLen += iLen;
  2753. X        }
  2754. X
  2755. X
  2756. X    /** advance element ref **/
  2757. X
  2758. X    iEltIndex ++;
  2759. X
  2760. X    } /* while */
  2761. X
  2762. X    
  2763. X    return(iErr);
  2764. X
  2765. X    } /* Native_VectToMessage */
  2766. X/****************************************************************************************/
  2767. X
  2768. X
  2769. X
  2770. X
  2771. X/****************************************************************************************/
  2772. XTVeosErr Native_MessageToXElt(pBuffer, hXElt, pLen)
  2773. X    char        *pBuffer;
  2774. X    LVAL         *hXElt;
  2775. X    int            *pLen;
  2776. X{
  2777. X    TVeosErr        iErr = VEOS_SUCCESS;
  2778. X    int            iLen, iType;
  2779. X    TF2L        fTrans;
  2780. X
  2781. X    *hXElt = NIL;
  2782. X
  2783. X    iType = ntohl(*(int *) pBuffer);    /** assume pBuffer is aligned **/
  2784. X
  2785. X    pBuffer += 4;
  2786. X    *pLen += 4;
  2787. X
  2788. X    switch (iType) {
  2789. X        
  2790. X    case GR_grouple:
  2791. X    iLen = 0;
  2792. X    iErr = Native_MessageToList(pBuffer, hXElt, &iLen);
  2793. X    break;
  2794. X
  2795. X    case GR_vector:
  2796. X    iLen = 0;
  2797. X    iErr = Native_MessageToVect(pBuffer, hXElt, &iLen);
  2798. X    break;
  2799. X
  2800. X    case GR_int:
  2801. X    *hXElt = cvfixnum((int) ntohl(*(long *) pBuffer));
  2802. X    iLen = 4;
  2803. X    break;
  2804. X             
  2805. X    case GR_float:
  2806. X    fTrans.u.l = ntohl(*(long *) pBuffer);
  2807. X    *hXElt = cvflonum(fTrans.u.f);
  2808. X    iLen = 4;
  2809. X    break;
  2810. X
  2811. X    case GR_string:
  2812. X    *hXElt = cvstring(pBuffer);
  2813. X    iLen = MEMSIZE(strlen(pBuffer) + 1);  
  2814. X    break;
  2815. X
  2816. X    case GR_prim:
  2817. X    *hXElt = xlenter(pBuffer);
  2818. X    iLen = MEMSIZE(strlen(pBuffer) + 1);  
  2819. X    break;
  2820. X
  2821. X    case GR_unspecified:
  2822. X    default:
  2823. X    iLen = 0;
  2824. X    break;
  2825. X        
  2826. X    } /* switch */
  2827. X
  2828. X    *pLen += iLen;
  2829. X    
  2830. X    return(iErr);
  2831. X
  2832. X    } /* Native_MessageToXElt */
  2833. X/****************************************************************************************/
  2834. X
  2835. X
  2836. X
  2837. X/****************************************************************************************/
  2838. XTVeosErr Native_MessageToList(pBuffer, hList, pLen)
  2839. X    char    *pBuffer;
  2840. X    LVAL    *hList;
  2841. X    int        *pLen;
  2842. X{
  2843. X    TVeosErr    iErr = VEOS_SUCCESS;
  2844. X    LVAL    pXFinger;
  2845. X    int        iLen, iElts, iEltIndex;
  2846. X    char    *pListHead;
  2847. X    LVAL    pList, pXElt;
  2848. X
  2849. X    xlstkcheck(2);
  2850. X    xlsave(pList);
  2851. X    xlsave(pXElt);
  2852. X
  2853. X    /** extract # of elements from first part of grouple data **/
  2854. X
  2855. X    iElts = ntohl(*(int *) pBuffer);
  2856. X
  2857. X    pBuffer += 4;
  2858. X    *pLen += 4;
  2859. X
  2860. X
  2861. X    /** convert each element one at a time, 'talk msg format' -> list' **/
  2862. X
  2863. X    iEltIndex = 0;
  2864. X    while (iEltIndex < iElts) {
  2865. X
  2866. X    iLen = 0;
  2867. X
  2868. X    /** extract elt data, allocate specific elt mem, stuff it with data. **/
  2869. X
  2870. X    iErr = Native_MessageToXElt(pBuffer, &pXElt, &iLen);
  2871. X
  2872. X    if (iErr != VEOS_SUCCESS)
  2873. X        break;
  2874. X
  2875. X    else {
  2876. X        pBuffer += iLen;
  2877. X        *pLen += iLen;
  2878. X
  2879. X        pList = cons(pXElt, pList);
  2880. X        }
  2881. X
  2882. X    iEltIndex ++;
  2883. X    }
  2884. X
  2885. X    if (iErr == VEOS_SUCCESS) {
  2886. X
  2887. X    *hList = ReverseList(pList);
  2888. X    }
  2889. X
  2890. X    xlpopn(2);
  2891. X
  2892. X    return(iErr);
  2893. X
  2894. X    } /* Native_MessageToList */
  2895. X/****************************************************************************************/
  2896. X
  2897. X
  2898. X
  2899. X
  2900. X/****************************************************************************************/
  2901. XTVeosErr Native_MessageToVect(pBuffer, hVect, pLen)
  2902. X    char    *pBuffer;
  2903. X    LVAL    *hVect;
  2904. X    int        *pLen;
  2905. X{
  2906. X    TVeosErr    iErr = VEOS_SUCCESS;
  2907. X    int        iLen, iElts, iEltIndex;
  2908. X    LVAL    pVect, pXElt;
  2909. X
  2910. X    xlstkcheck(2);
  2911. X    xlsave(pVect);
  2912. X    xlsave(pXElt);
  2913. X
  2914. X    /** extract # of elements from first part of grouple data **/
  2915. X
  2916. X    iElts = ntohl(*(int *) pBuffer);
  2917. X
  2918. X    pBuffer += 4;
  2919. X    *pLen += 4;
  2920. X
  2921. X
  2922. X    /** create new lisp vector as container **/
  2923. X
  2924. X    pVect = newvector(iElts);
  2925. X
  2926. X
  2927. X    /** convert each element one at a time **/
  2928. X
  2929. X    iEltIndex = 0;
  2930. X    while (iEltIndex < iElts) {
  2931. X
  2932. X    iLen = 0;
  2933. X
  2934. X    /** extract elt data, allocate specific elt mem, stuff it with data. **/
  2935. X
  2936. X    iErr = Native_MessageToXElt(pBuffer, &pXElt, &iLen);
  2937. X    if (iErr != VEOS_SUCCESS) 
  2938. X        break;
  2939. X
  2940. X    else {
  2941. X        pBuffer += iLen;
  2942. X        *pLen += iLen;
  2943. X
  2944. X        setelement(pVect, iEltIndex, pXElt);
  2945. X        }
  2946. X
  2947. X    iEltIndex ++;
  2948. X    }
  2949. X
  2950. X
  2951. X    if (iErr == VEOS_SUCCESS)
  2952. X    *hVect = pVect;
  2953. X
  2954. X    xlpopn(2);
  2955. X
  2956. X    return(iErr);
  2957. X
  2958. X    } /* Native_MessageToVect */
  2959. X/****************************************************************************************/
  2960. X
  2961. X
  2962. X
  2963. X/****************************************************************************************/
  2964. XTVeosErr Native_TrapErr(iErr, pXElt)
  2965. X    TVeosErr    iErr;
  2966. X    LVAL    pXElt;
  2967. X{
  2968. X    str63    sErr;
  2969. X
  2970. X    switch(iErr) {
  2971. X
  2972. X    case NATIVE_BADTYPE:
  2973. X    xlbadtype(pXElt);
  2974. X    break;
  2975. X    case NATIVE_NOKERNEL:
  2976. X    xlfail("veos kernel not initialized, use (vinit <port-num>)");
  2977. X    break;
  2978. X    case NATIVE_BADFREQ:
  2979. X    xlerror("'!' expected", pXElt);
  2980. X    break;
  2981. X    case NATIVE_2KERNELS:
  2982. X    xlfail("veos kernel already initialized");
  2983. X    break;
  2984. X    case NATIVE_BADVTYPE:
  2985. X    xlerror("veos does not support that data type", pXElt == nil ? s_unbound : pXElt);
  2986. X    break;
  2987. X    case NATIVE_BADXTYPE:
  2988. X    xlerror("xlisp does not support that data type from veos",
  2989. X        pXElt == nil ? s_unbound : pXElt);
  2990. X    break;
  2991. X    case NATIVE_EMPTYELT:
  2992. X    xlerror("empty data element from veos, probably a memory error",
  2993. X        pXElt == nil ? s_unbound : pXElt);
  2994. X    break;
  2995. X    case NATIVE_NODATA:
  2996. X    xlerror("no veos data to match... only the void remains", s_unbound);
  2997. X    break;
  2998. X    case NATIVE_THISWHAT:
  2999. X    xlerror("pattern element modifier ('>' or '~') must be followed by a matchable element", pXElt == nil ? s_unbound : pXElt);
  3000. X    break;
  3001. X    case NATIVE_TOOMANYMARKS:
  3002. X    xlerror("patterns must contain exactly one '>' or '^'",
  3003. X        pXElt == nil ? s_unbound : pXElt);
  3004. X    break;
  3005. X    case NATIVE_CANTMIX:
  3006. X    xlerror("can't mix '@' and '*'", pXElt == nil ? s_unbound : pXElt);
  3007. X    break;
  3008. X    case NATIVE_NOTEND:
  3009. X    xlerror("indefinite wildcards (eg '@@' or '**') can only appear at end of grouple in pattern",
  3010. X        pXElt == nil ? s_unbound : pXElt);
  3011. X    break;
  3012. X    case NATIVE_NOREPLACEMARK:
  3013. X    xlerror("pattern must contain '>' or '^'", pXElt == nil ? s_unbound : pXElt);
  3014. X    break;
  3015. X    case NATIVE_NOFETCHMARK:
  3016. X    xlerror("pattern must contain '>'", pXElt == nil ? s_unbound : pXElt);
  3017. X    break;
  3018. X    case NATIVE_NOVOID:
  3019. X    xlerror("cannot get or copy from the void ('^')",  
  3020. X        pXElt == nil ? s_unbound : pXElt);
  3021. X    break;
  3022. X    case NATIVE_BADPATSYMBOL:
  3023. X    xlerror("symbol not recognized", pXElt == nil ? s_unbound : pXElt);
  3024. X    break;
  3025. X    case NATIVE_CRAZYWILD:
  3026. X    xlerror("nonsensical number of wildcard elements",
  3027. X        pXElt == nil ? s_unbound : pXElt);
  3028. X    break;
  3029. X    case NATIVE_MATCHFAIL:
  3030. X    xlerror("match and/or replace did not succeed",
  3031. X        pXElt == nil ? s_unbound : pXElt);
  3032. X    break;
  3033. X    case NATIVE_NOSTARN:
  3034. X    xlerror("the '*n' feature is not supported",
  3035. X        pXElt == nil ? s_unbound : pXElt);
  3036. X    break;
  3037. X    case NATIVE_BADVOID:
  3038. X    xlerror("ambiguous void marker (can't use '^' in pattern grouple containing '*')",
  3039. X        pXElt == nil ? s_unbound : pXElt);
  3040. X    break;
  3041. X    case NATIVE_NOHOST:
  3042. X    xlerror("host not recognized", pXElt == nil ? s_unbound : pXElt);
  3043. X    break;
  3044. X    case NATIVE_NOTOUCH:
  3045. X    xlerror("can't touch (eg. '~') elements during nondestructive grouplespace access", pXElt == nil ? s_unbound : pXElt);
  3046. X    break;
  3047. X    case NATIVE_MODVOID:
  3048. X    xlerror("can't use element modifiers ('>' or '~') with the void ('^')", pXElt == nil ? s_unbound : pXElt);
  3049. X    break;
  3050. X    case VEOS_SUCCESS:
  3051. X    break;
  3052. X    default:
  3053. X    sprintf(sErr, "unexpected error %d", iErr);
  3054. X    xlerror(sErr, pXElt == nil ? s_unbound : pXElt);
  3055. X    break;
  3056. X    }
  3057. X
  3058. X    return(VEOS_SUCCESS);
  3059. X
  3060. X    } /* Native_TrapErr */
  3061. X/****************************************************************************************/
  3062. X
  3063. X
  3064. X
  3065. X/****************************************************************************************/
  3066. Xboolean    IsUidElt(pXElt)
  3067. X    LVAL    pXElt;
  3068. X{
  3069. X    return(vectorp(pXElt) &&
  3070. X       getsz(pXElt) == 2 &&
  3071. X       stringp(getelement(pXElt, 0)) &&
  3072. X       fixp(getelement(pXElt, 1)));
  3073. X
  3074. X    } /* IsUidElt */
  3075. X/****************************************************************************************/
  3076. X
  3077. X
  3078. X/****************************************************************************************/
  3079. XTVeosErr XVect2Uid(pXElt, pUid)
  3080. X    LVAL    pXElt;
  3081. X    TPUid    pUid;
  3082. X{
  3083. X    TVeosErr    iErr;
  3084. X
  3085. X    /** assume sanity is checked **/
  3086. X
  3087. X    iErr = Sock_ResolveHost(getstring(getelement(pXElt, 0)), &pUid->lHost);
  3088. X    if (iErr == VEOS_SUCCESS)
  3089. X    pUid->iPort = getfixnum(getelement(pXElt, 1));
  3090. X    else
  3091. X    iErr = NATIVE_NOHOST;
  3092. X
  3093. X    return(iErr);
  3094. X
  3095. X    } /* XVect2Uid */
  3096. X/****************************************************************************************/
  3097. X
  3098. X
  3099. X/****************************************************************************************/
  3100. XTVeosErr Uid2XVect(pUid, hXElt)
  3101. X    TPUid    pUid;
  3102. X    LVAL    *hXElt;
  3103. X{
  3104. X    str255    sTemp;
  3105. X
  3106. X    /** assume sanity is checked **/
  3107. X
  3108. X    if (Sock_IP2StrHost(pUid->lHost, sTemp) == VEOS_SUCCESS ||
  3109. X    Sock_IP2StrAddr(pUid->lHost, sTemp) == VEOS_SUCCESS) {
  3110. X
  3111. X    /** assume caller locked *hXElt **/
  3112. X
  3113. X    *hXElt = newvector(2);
  3114. X    setelement(*hXElt, 0, cvstring(sTemp));
  3115. X    setelement(*hXElt, 1, cvfixnum(pUid->iPort));
  3116. X    }
  3117. X
  3118. X    return(VEOS_SUCCESS);
  3119. X
  3120. X    } /* Uid2XVect */
  3121. X/****************************************************************************************/
  3122. X
  3123. X
  3124. X
  3125. X/****************************************************************************************/
  3126. XTVeosErr Native_XVectsToUids(pList, hDests)
  3127. X    LVAL    pList;
  3128. X    THUidNode    hDests;
  3129. X{
  3130. X    TVeosErr    iErr = VEOS_SUCCESS;
  3131. X    TPUidNode    pDests, pNode;
  3132. X    LVAL    pXFinger;
  3133. X
  3134. X    /** convert lisp 'uid' vectors to nancy uids **/
  3135. X
  3136. X    pDests = nil;
  3137. X    pXFinger = pList;
  3138. X    while (!null(pXFinger)) {
  3139. X
  3140. X#ifndef OPTIMAL    
  3141. X    if (!IsUidElt(car(pXFinger))) {
  3142. X        iErr = NATIVE_BADTYPE;
  3143. X        break;
  3144. X        }
  3145. X#endif
  3146. X    iErr = Shell_NewBlock(sizeof(TUidNode), &pNode, "uid-node");
  3147. X
  3148. X    if (iErr != VEOS_SUCCESS)
  3149. X        break;
  3150. X
  3151. X    else{
  3152. X        /** add new node to list **/
  3153. X        
  3154. X        pNode->pNext = pDests;
  3155. X        pDests = pNode;
  3156. X        
  3157. X        
  3158. X        /** convert addr to internal format **/
  3159. X        
  3160. X        iErr = XVect2Uid(car(pXFinger), &pNode->addr);
  3161. X        }
  3162. X
  3163. X    pXFinger = cdr(pXFinger);
  3164. X
  3165. X    } /* while */
  3166. X
  3167. X    if (iErr == VEOS_SUCCESS)
  3168. X    *hDests = pDests;
  3169. X    else
  3170. X    Native_DisposeUids(pDests);
  3171. X
  3172. X    return(iErr);
  3173. X
  3174. X    } /* Native_XVectsToUids */
  3175. X/****************************************************************************************/
  3176. X
  3177. X
  3178. X
  3179. X/****************************************************************************************/
  3180. XTVeosErr Native_DisposeUids(pDests)
  3181. X    TPUidNode    pDests;
  3182. X{
  3183. X    TPUidNode    pSave;
  3184. X
  3185. X    while (pDests) {
  3186. X
  3187. X    pSave = pDests->pNext;
  3188. X    Shell_ReturnBlock(pDests, sizeof(TUidNode), "uid-node");
  3189. X    pDests = pSave;
  3190. X    }
  3191. X
  3192. X    return(VEOS_SUCCESS);
  3193. X
  3194. X    } /* Native_DisposeUids */
  3195. X/****************************************************************************************/
  3196. X
  3197. X
  3198. X/****************************************************************************************/
  3199. XTVeosErr IsIntStr(sSrc)
  3200. X    char         *sSrc;
  3201. X{
  3202. X    TVeosErr    iErr;
  3203. X
  3204. X    iErr = VEOS_FAILURE;
  3205. X    if (sSrc) {
  3206. X
  3207. X    for (iErr = VEOS_SUCCESS;
  3208. X         sSrc[0] != '\0' && iErr == VEOS_SUCCESS;
  3209. X         sSrc ++)
  3210. X
  3211. X        if (!isdigit(sSrc[0]))
  3212. X        iErr = VEOS_FAILURE;
  3213. X    }
  3214. X
  3215. X    return(iErr);
  3216. X
  3217. X    } /* IsIntStr */
  3218. X/****************************************************************************************/
  3219. X
  3220. X
  3221. END_OF_FILE
  3222. if test 43094 -ne `wc -c <'src/kernel_current/shell/xv_glutils.c'`; then
  3223.     echo shar: \"'src/kernel_current/shell/xv_glutils.c'\" unpacked with wrong size!
  3224. fi
  3225. # end of 'src/kernel_current/shell/xv_glutils.c'
  3226. fi
  3227. echo shar: End of archive 14 \(of 16\).
  3228. cp /dev/null ark14isdone
  3229. MISSING=""
  3230. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
  3231.     if test ! -f ark${I}isdone ; then
  3232.     MISSING="${MISSING} ${I}"
  3233.     fi
  3234. done
  3235. if test "${MISSING}" = "" ; then
  3236.     echo You have unpacked all 16 archives.
  3237.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  3238. else
  3239.     echo You still need to unpack the following archives:
  3240.     echo "        " ${MISSING}
  3241. fi
  3242. ##  End of shell archive.
  3243. exit 0
  3244.